mail

New with Go 1.16, the //go:embed directive allows to embed files into your go artifacts. Templates for mails, websites, scripts can be added added more easily than ever

TL;DR: //go:embed is a directive that fills a variable or a dedicated type that implements the io/fs.FS interface with a set of files and directories. New with Go 1.16, it is very useful to distribute Go artifacts that embed content like templates, scripts or web pages and remove the need for third party libraries. Because it is embedded within the toolchain //go:embed does not require you run any commands during the build process.

The TL;DR: says it all, you'll find 2 simple examples below.

A simple example

The simplest way of using embed is by adding the directive to a string or []byte variable like in the example below. In order for it to work, you would need:

  • to add //go:embed with the path of the file to load above the variable
  • to reference the library in imports with _ "embed"
  • to have a file in the same directory named index.txt that contains, for instance Hello World!

This is an example of such a program:

package main

import (
	_ "embed"
	"fmt"
)

//go:embed index.txt
var helloworld string

func main() {
	fmt.Printf("%s", helloworld)
}

The execution of your program looks like below:

go run main.go
Hello World!

A more advanced example

If you have several files or if you need to manipulate your content with something that looks like a directory, Go 1.16 provides an interface called FS in io/fs. The interface allows to manage the content of your embedded files as if they were files on a read-only filesystem.

To use embed in that context, you should create an variable with embed.FS as a type. In order for it to work, you would need:

  • to add //go:embed with one or several file patterns above the variable
  • to reference the library in imports with "embed"
  • files with the content you plan to serve somehow

This is an example of such a program that uses embed.FS:

package main

import (
	"embed"
	"fmt"
)

//go:embed index.txt
var fs embed.FS

func main() {
	data, _ := fs.ReadFile("index.txt")
	fmt.Printf("%s", string(data))
}

The execution of your program looks like below:

go run main.go
Hello World!

To continue

As a matter of fact, there is not much more to say than that. It is a quite simple interface. It provides an elegant way to replace other tools like go-bindata, gobuffalo/packr, markbates/pkger or mjibson/esc. The best of it, being you do not have to use a Makefile or go generate to use it.

Bibliography

If you are interested to read more about "embed", check the following URLs: