Understanding Go 1.16 embed: Use Cases, Implementation Details, and Design Rationale
This article explains the Go 1.16 embed feature by describing the typical configuration‑file problem, showing traditional file‑reading code versus embed‑based code, and diving into the compiler’s embedcfg handling and the underlying design philosophy of the new io/fs package.
The author, a backend engineer at Tencent IEG Growth Platform, introduces Go 1.16’s new embed feature and outlines three main topics: practical use cases, the source‑level implementation, and the design ideas behind it.
When deploying a new project, configuration files placed alongside the source code are not automatically bundled into the container image, causing the binary to fail at runtime because it cannot locate the required files.
Traditionally, developers read configuration files with code like the following, which expects the file to exist next to the binary:
func main() {
fPath := "conf/conf.ini"
c, err := ioutil.ReadFile(fPath)
if err != nil {
log.Fatal(err)
}
fmt.Println(string(c))
}Using go:embed , the same file can be compiled directly into the binary, eliminating the need for external copies. The embed declaration and usage look like this:
//go:embed conf/conf.ini
var f embed.FS
func main() {
fPath := "conf/conf.ini"
data, err := f.ReadFile(fPath)
if err != nil {
log.Fatal(err)
}
fmt.Println(string(data))
}The implementation is a compile‑time operation. The Go compiler scans for go:embed directives, writes the referenced file paths into an embedcfg file, and later the initEmbed routine reads those files, converting them into symbols that are linked into the final .a package. Key functions such as fileStringSym perform the actual file system calls (open, stat) during this phase.
Beyond solving the configuration‑file problem, go:embed was introduced to support the new io/fs package, which provides a generic, read‑only file‑system abstraction inspired by the Unix “everything is a file” philosophy. The generated FS object implements the fs.FS interface, whose Open method returns a fs.File that can be used like a regular file but is read‑only. This design moves away from the older os.File model and aligns Go with more modern, portable file‑system handling.
Although the current FS implementation is read‑only, proposals for write capabilities are already under discussion, indicating the design will continue to evolve.
In conclusion, go:embed provides a seamless way to embed static assets into Go binaries, preserves compatibility with existing APIs (e.g., ioutil.ReadFile vs. embed.FS.ReadFile ), and lays the groundwork for a richer, cross‑platform file‑system abstraction.
IEG Growth Platform Technology Team
Official account of Tencent IEG Growth Platform Technology Team, showcasing cutting‑edge achievements across front‑end, back‑end, client, algorithm, testing and other domains.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.