Embedding static files in Go

Bhupesh Varshney ๐Ÿ‘พ - Feb 12 '21 - - Dev Community

Embedding static files in 2021 has become a bit easier since the release of Go 1.16. The new release comes with a new module embed which provides a handy set of interface and methods to attach static files in go binaries

Letโ€™s have a short look at how to use this.

First of all, you will need Go 1.16

$ go get golang.org/dl/go1.16rc1
$ go1.16rc1 download
$ go1.16rc1 version
go version go1.16rc1

Enter fullscreen mode Exit fullscreen mode

Now before we do that, letโ€™s create a project directory

$ tree
.
โ”œโ”€โ”€ assets
โ”‚   โ””โ”€โ”€ report.html
โ”œโ”€โ”€ sample.txt
โ””โ”€โ”€ static-demo.go

Enter fullscreen mode Exit fullscreen mode

Our code will be in static-demo.go

Go provides us with 3 ways to embed content:

  1. On type string
  2. On type byte
  3. On type FS

Letโ€™s explore each one of these one by one

package main

import (
    _ "embed"
    "fmt"
)

func main() {

    //go:embed sample.txt
    var s string
    fmt.Println(s)

}

Enter fullscreen mode Exit fullscreen mode

To specify what variable holds our static file, go directive //go:embed is used followed by the name of file or a pattern to embed. Note that there must be no space between // and go because that is a regular one line comment in Go.

The //go:embed directive requires importing โ€œembedโ€, even when using a string or []byte & since we are not referring to the embed module directly we are using a blank _ import. In our code we are embedding a text file sample.txt here is what it contains

This is a sample file
with multiple lines

and ๐Ÿง๏ธ emojis too!

Enter fullscreen mode Exit fullscreen mode

Now lets execute our code to see if actually works

$ go run static-demo.go
This is a sample file
with multiple lines

and ๐Ÿง๏ธ emojis too!

Enter fullscreen mode Exit fullscreen mode

Ok thatโ€™s pretty cool (dodge this Javascript!). Now lets see how to share some data to a text file

package main

import (
    "embed"
    "fmt"
    "html/template"
    "os"
)

func main() {
    //go:embed assets/*
    var assetData embed.FS
    t, err := template.ParseFS(assetData, "assets/report.html")
    if err != nil {
        fmt.Println(err)
    }
    templateData := struct {
        Title string
    }{
        Title: "File inside Go",
    }
    t.Execute(os.Stdout, templateData)
}

Enter fullscreen mode Exit fullscreen mode

embed.FS enables us to embed a tree of static files i.e in our case the assets directory as dictated by the directive //go:embed assets/* which contains a file report.html with following contents

<html>
  <head>
    <title>{{$.Title}}</title>
  </head>
  <body>
    <h1>Go is cool af!</h1>
  </body>
</html>

Enter fullscreen mode Exit fullscreen mode

Patterns in the go directive cannot contain โ€˜.โ€™ or โ€˜..โ€™ path elements nor begin with a leading slash. To match everything in the current directory, use โ€˜*โ€™

A FS (file system) in Go is a read-only collection of files, usually initialized with a //go:embed directive.

template.ParseFS takes a FS as first argument followed by a list of glob patterns,

Running this prints out our title correctly inside the HTML template.

$ go run static-demo.go 
<html>
  <head>
    <title>File inside Go</title>
  </head>
  <body>
    <h1>Go is cool af!</h1>
  </body>
</html>

Enter fullscreen mode Exit fullscreen mode

It worked!

Embedding files inside the binaries itself opens up emense out of opportunities that we would see as this feature gets stable

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Terabox Video Player