Embed file in a Go binary

Author

Gurleen Sethi on 19 August 2022

Embed file in a Go binary

Getting Started #

In this article I am going to show you how to embed static files inside a Go binary. Embedding files can serve many purposes such as embedding a React app and serving it over http all inside a single Go binary.

Embed a single file #

We will start by embedding a single file and print it out to standard output.

Let's prepare a simple index.html static file.

<html>
  <head>
      <title>Embedded File</title>
  </head>
  <body>
      <h1>Hello from Go!</h1>
  </body>
</html>
index.html

Write the Go code to embed the file.

package main

import (
	_ "embed"
	"fmt"
)

//go:embed index.html
var staticFile string

func main() {
	fmt.Println(staticFile)
}
main.go

For embedding to work you need three things:

  1. Import the embed package (import _ "embed").
  2. A variable to hold the data of embedded file (var staticFile string).
  3. Using comment specify which file to import //go:embed index.html. The comment goes right above the variable.

Note: Both main.go and index.html are in the same directory. Go will look for the file relative to the main.go file.

Build the binary using go build and run it, the html file will be the output.

<head>
    <title>Embedded File</title>
</head>
<body>
    <h1>Hello from Go!</h1>
</body>
</html>

There are 3 valid types for the variable that holds embedded file: string, []byte and embed.FS.

Embed a directory #

Instead of embedding a single file, we can embed an entire directory.

Let's prepare a directory, create a new static folder and place the index.html file in it.

Create a new page.html file in the static folder.

<html>
    <head>
        <title>Embedded File</title>
    </head>
    <body>
        <h1>Page</h1>
    </body>
</html>
static/page.html

So the folder structure looks like this.

static
  |- index.html
  |- page.html
main.go

Since we are embedding a directory we will use embed.FS type here.

package main

import (
	"embed"
	"fmt"
)

//go:embed static
var fs embed.FS

func main() {
	files, _ := fs.ReadDir("static")

	for _, f := range files {
		fmt.Println(f.Name())
	}
}
main.go

embed.FS has a function called ReadDir that lists the content of a directory, in the above code example we list all the files inside the static folder.

The output will be:

index.html
page.html

Reading one of the files from the directory

package main

import (
	"embed"
	"fmt"
)

//go:embed static
var fs embed.FS

func main() {
	file, _ := fs.ReadFile("static/index.html") // 👈
	fmt.Println(string(file))
}
main.go

Embed multiple directories #

You can go one step ahead and embed multiple folders. Let's create a new static2 folder and paste the same index.html folder.

package main

import (
	"embed"
	"fmt"
)

//go:embed static static2
var fs embed.FS

func main() {
	files, _ := fs.ReadDir(".")

	for _, f := range files {
		fmt.Println(f.Name())
	}
}
main.go

In the embedding comment, specify another folder separated with a space //go:embed static static2.

The output will be:

static
static2

Serve embedded directory over http #

We can take advantage of this embedding feature and serve our static files over http using.

package main

import (
	"embed"
	"net/http"
)

//go:embed static
var fs embed.FS

func main() {
	http.Handle("/", http.FileServer(http.FS(fs)))
	http.ListenAndServe(":8080", nil)
}
main.go

Visit http://localhost:8080/static/index.html in your browser to see the file in action.

Read more about embed package and its functionality on the official docs here.

Thank you for reading this article 🙏🏻 please consider joining the mailing list below.

Table of Contents
Subscribe via email

Get notified once/twice per month when new articles are published.

Byte Byte Go Affiliate
TheDeveloperCafe
Copyright © 2022 - 2024 TheDeveloperCafe.
The Go gopher was designed by Renee French.