Menu Close

Embedding Files in Go Binaries

In other programming languages like Java, it is common to embed static files or resources in a deployable build artifact, for example, a .jar File. This approach is used to store template data, images, configuration files, or any other type of static data items required when running the program. This article explains how to achieve the same with Go Binaries.

Since Go 1.16

Since many Go developers required embedded resources in their binaries, the Go Team introduced this feature with Go Version 1.16. You can use it by importing the “embed” package and using the //go:embed directive. Here are some examples:

Embedding a file as string

We want to embed the text file test.txt with following content:

This file will be embed in your Go build artifact.

Have fun with this awesome new Go feature.

The simplest method is to embed the resource as a string variable like this:

package main

import (
	_ "embed"
	"fmt"
)

//go:embed test.txt
var stringFile string

func main() {
	fmt.Println(stringFile)
}

Notice that we’re using “_” to import the “embed” package, because if a package is not directly used by your code, Go would return a build error when you import it.

There are also some other usefull embedding options:

Embedding a file as byte slice

This method is useful when embed files should be used as input for io.Writer Interface implementation since the Input for the Write method is byte slice:

package main

import (
	_ "embed"
	"os"
)

//go:embed test.txt
var byteFile []byte

func main() {
	os.Stdout.Write(byteFile)
}

Embedding multiple files as embed.FS

You can also embed multiple files at once as an embed.FS (File System), which can be used as http.FileSystem to serve a static web page from your single file go binary. For example, you can embed all files in the html folder of a project and serve the files with a webserver like this:

package main

import (
	"embed"
	"net/http"
)

//go:embed html/*
var fs embed.FS

func main() {

	http.Handle("/resources/", http.StripPrefix("/resources/", http.FileServer(http.FS(fs))))

	http.ListenAndServe(":8080", http.DefaultServeMux)
}

You can also import multiple folders and files based on file path patterns. For a full explanation of possible embed directive entries view the Go documentation of the embed package.

Before Go 1.16

Prior to Go 1.16 embedding files in a Go Binary was not a standard feature. You had to choose between using an external package or implementing your own approach to embed your files. I don’t like to reinvent the wheel, that’s why I would advise using an external package. One that worked great for me was https://github.com/rakyll/statik

This repository also has a great README, which explains how to use the package in detail, so I’ll not repeat all of it in this article.

Leave a Reply

Your email address will not be published.