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?

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

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

Example web server with go embed
Web page template: index.html.tmpl

Let’s build and deploy the web server.

$ go version
go version go1.16 darwin/arm64
$ go build . # Build the binary$ cp ./go-embed /tmp/ # copy to temp directory. This would help validate that static files are actually embedded$ cd /tmp && ./go-embed # Run the server2020/12/18 12:21:15 Listening on :3000...
2020/12/18 12:21:23 Serving request for path /some-path-with-css-applied
2020/12/18 12:21:23 Serving request for path /favicon.ico
2020/12/18 12:21:24 Serving request for path /some-path-with-css-applied
2020/12/18 12:21:24 Serving request for path /favicon.ico
2020/12/18 12:21:25 Serving request for path /some-path-with-css-applied
2020/12/18 12:21:25 Serving request for path /favicon.ico

Browse to http://localhost:3000/

Web server serving content embedded by go embed

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

Image Credits: https://gopherize.me/gopher/56d6068d1995da6db9297b5d8b27add7f523ee2f

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