DEV Community

loading...

Embedding static files in Go

bhupesh profile image Bhupesh Varshney ๐Ÿ‘พ Originally published at bhupesh-v.github.io on ใƒป2 min read

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

Discussion (2)

pic
Editor guide
Collapse
ja7ad profile image
Javad Rajabzade • Edited

Thank you for this post , in

//go:embed sample.txt
var s string
fmt.Println(s)
Enter fullscreen mode Exit fullscreen mode

sample.txt auto embed to s string ?

For byte embed what do it?

Collapse
bhupesh profile image
Bhupesh Varshney ๐Ÿ‘พ Author

Hi Javad, Sorry for the late reply. I just saw your comment
You just need to declare a byte variable to do this

    //go:embed sample.txt
    var b []byte
    fmt.Println(b)
Enter fullscreen mode Exit fullscreen mode