Using Go Embed
The go:embed
feature simplifies the inclusion of static assets in your Go applications. By embedding files and directories at compile time, you can create more portable and self-contained binaries.
With the release of Go 1.16, go:embed
was introduced. This new code comment (we call it a directive) allows you to embed static files and folders into your Go binaries. If you’re building web servers that serve static content or building command-line tools that require configuration files, go:embed
simplifies the process by eliminating the need for external file handling. It also means that your binary contains everything you need to ship your code. Powerful!
What is go:embed?
The go:embed
directive tells the Go compiler to include files and folders into the compiled binary at build time. This means your application can access these resources directly from memory without needing to read from the disk at runtime.
To use go:embed
, you’ll need Go version 1.16 or later. Here’s a simple example of how you could embed a single file:
Firstly, make a txt file called message.txt
. It can contain whatever you want - something like:
hello from bytesizego!
and write the following code in main.go
package main
import (
_ "embed"
"fmt"
)
//go:embed message.txt
var message string
func main() {
fmt.Println(message)
}
In this very small program we are:
- Importing the blank identifier
_
for the embed package to enable thego:embed
directive. - Using the
//go:embed message.txt
directive specifies to specify the file to embed. - Adding a
message
variable to hold the content ofmessage.txt
as a string.
As you’d expect, this program outputs:
hello from bytesizego!
Embedding Multiple Files
Let’s make it a little more complicated:
package main
import (
_ "embed"
"fmt"
)
//go:embed messages/*.txt
var messages embed.FS
func main() {
files, _ := messages.ReadDir("messages")
for _, file := range files {
data, _ := messages.ReadFile("messages/" + file.Name())
fmt.Printf("File: %snContent: %snn", file.Name(), data)
}
}
Here:
- We use
embed.FS
to embed multiple files. - The
ReadDir
andReadFile
methods allow us to interact with the embedded files.
Embedding Directories
You can also embed entire folders:
package main
import (
"embed"
"fmt"
)
//go:embed static
var staticFiles embed.FS
func main() {
data, _ := staticFiles.ReadFile("static/index.html")
fmt.Println(string(data))
}
Tip: When embedding directories, the path specified in ReadFile
is relative to the embedded root.
Using go embed to Create a Web App
Super simple!
package main
import (
"embed"
"net/http"
)
//go:embed static/*
var staticFiles embed.FS
func main() {
http.Handle("/", http.FileServer(http.FS(staticFiles)))
http.ListenAndServe(":8080", nil)
}
Run the program, and now you can access your embedded static files via http://localhost:8080.
Using go embed to Embed Files into a Struct
Maybe you want to embed stuff to use later in your program. Putting it on a struct is probably what you want. This could be useful for configuration.
package main
import (
"embed"
"fmt"
)
//go:embed templates/home.html
var homeTemplate string
//go:embed templates/about.html
var aboutTemplate string
type Templates struct {
Home string
About string
}
func main() {
t := Templates{
Home: homeTemplate,
About: aboutTemplate,
}
fmt.Println("Home Template:", t.Home)
fmt.Println("About Template:", t.About)
}
Using go Embed to Embed Images and PDFs
If you’re working with non-text files (like images or PDFs), you should use a byte slice:
package main
import (
_ "embed"
"fmt"
)
//go:embed image.webp
var imageData []byte
func main() {
fmt.Printf("Image size: %d bytesn", len(imageData))
}
Be careful with this! Here’s some limitations:
- File Size: Embedding large files can significantly increase your binary size.
- File Changes: Changes to the embedded files require recompilation.
Wrapping up
go embed
is amazing! I see it rarely used, but I use it often now, especially when creating web apps.
If you found this blog useful, check out our other blogs or join our mailing list which will send you a list of 60+ companies hiring Go engineers remotely right now.