Embedding static files in a go binary using go embed

Starting with Golang 1.16, file embedding is supported in Go without the need of an external package. I have been using packages like pkgr and packr to make it easier to embed static files in go binaries. We’ll explore the usage of the new //go:embed directive in this post.

Why do we need static file embedding?

There would be cases when we’d want to embed static files in the binary. While it is possible to build a binary that reads static files off the disk, it is often cumbersome to ship it to end users as the static files have to be located at a certain place on user’s device or the location has to be configurable. On top of that, the user must remember to update all the files/config refs when upgrading or moving the binary to a new location.

Here are some common use cases where static file embedding is often used:

Go templates: The template files need to be available to the binary. This is a fairly common use case for web server binaries or CLI applications offering an init command which creates a sample project. In absence of embedding, the templates are often inlined in the code. eg: See qbec init or the source.

Static web servers: Sometimes static files like an index.html or other HTML, JavaScript and CSS files need to be shipped with a golang server binary so that the user can run the server and serve these files. eg: Static file embedding in a web server

Database migrations: Another place where embedded files can be used is to ship database migration scripts with the binary. eg: Database migration files

Using the go embed directive

The first thing you need to use the embed directive is to make sure that you are using at-least golang 1.16. For older versions of Go, consider using pkgr.

We’ll write an application that runs a web app which echoes the url back in a webpage (Fancy!! isn’t it?)

The program reads the web page title from a static title.txt file, serves static files (css/main.css) over the /static/ route and uses a go template index.html.tmpl to render all routes over HTTP port 3000. All static files and templates are embedded in the binary using the new embed directive.

Project structure:
.
├── go.mod
├── main.go
├── static
│ └── css
│ └── main.css
├── templates
│ └── index.html.tmpl
└── title.txt

Let’s build and deploy the web server.

Browse to http://localhost:3000/

The final result is a single web server binary ready for distribution. For more information check out the official embed documentation. Happy embedding.

The source code for the server is available at

Personal views

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store