It is possible to place files directly inside Go executables when compiled. This allows us to create single-file websites and other applications with minimal runtime dependencies.
With the embed package, we can use directives within comments that indicate files. These directives are replaced with file contents during compilation.
Here we use the embed module in the simplest way possible—by embedding a text file as a string
. Please note the exact syntax of the "go:embed" statement within comments.
exampleTxt
" string
.package main
import (
"fmt"
_ "embed"
)
//go:embed example.txt
var exampleTxt string
func main() {
// Print the length of embedded string, and also the string itself.
fmt.Println(len(exampleTxt))
fmt.Println(exampleTxt)
}18
Some example text.
We can embed an entire file system into our Go executable. We use the same "go:embed" statement, but with multiple file names, and follow it with a "embed.FS
" variable.
WalkDir
with 3 arguments.WalkDir
is the name of the embed.FS
—here we used the identifier "x."func
that is called on each file found by WalkDir
. In this func
, we access each file, and print its path and contents.package main
import (
"fmt"
"io/fs"
"embed"
)
//go:embed example.txt output.webp
var x embed.FS
func main() {
// Walk all files in the embedded file system.
fs.WalkDir(x, ".", func(path string, d fs.DirEntry, err error) error {
// Ignore error.
if err != nil {
return nil
}
// Skip period path.
if path == "." {
return nil
}
fmt.Println("PATH:", path)
// Read file.
content, _ := fs.ReadFile(x, path)
// Print file length and file if it is short.
fmt.Println("FILE LENGTH:", len(content))
if len(content) <= 50 {
fmt.Println("FILE CONTENTS:", string(content))
}
return nil
})
}PATH: example.txt
FILE LENGTH: 18
FILE CONTENTS: Some example text.
PATH: output.webp
FILE LENGTH: 4796
With the embed module, we can embed files as strings, and even entire file systems which we can later access with WalkDir
. We can open each embedded file and display its contents.