Go compiles programs that are perfect for deployment, and if no other libraries are referenced through CGO, we generally compile executable binaries that are single files, perfect for copying and deployment. In practice, in addition to binaries, you may also need some configuration files, or static files, such as html templates, static images, CSS, javascript, etc. How these files can also be typed into the binary would be fantastic, and we could just copy and follow the single executable.
Some open source projects started doing this a long time ago, such as gobuffalo/packr, markbates/pkger, rakyll/statik, knadh/stuffbin, etc., but anyway these are all third-party provided features, and it would be nice if Go could officially build in support. late 2019 a proposal was raised in issue#35950, expecting the official Go compiler to support embedded static files. Russ Cox later wrote a design document for Go command support for embedded static assets, and eventually implemented it.
Go 1.16 already includes the go embed feature, so you can try it out to your heart’s content.
In this article, we will go through examples and introduce the various features of go embed in detail.
Embed
- For single files, embedding as strings and byte slice is supported
- For multiple files and folders, support for embedding as a new file system FS
- For example, importing an “embed” package, even without explicitly using the
- The
go:embed
directive is used for embedding and must be followed by the variable name immediately after embedding - FS only supports embedding as
string
,byte slice
andembed.FS
three types, these three types of alias (alias) and named types (such as type S string) are not available
1, Embed as string
For example, there is a hello.txt file under the current file, and the content of the file is hello,world! With the go:embed directive, the value of the s variable in the following program becomes hello,world! after compilation.
2, Embed as byte slice
You can also embed the contents of a single file as a slice of byte, which is an array of bytes.
3, Embed as fs.FS
You can even embed as a file system, which is very useful when embedding multiple files.
For example, to embed a file:
Embedding another local file hello2.txt, supporting multiple go:embed
directives on the same variable (embedding as string or byte slice is not possible with multiple go:embed
directives):
The current duplicate go:embed command embedded as embed.FS is supported and will automatically remove duplicates:
It is also possible to embed files under subfolders.
Pattern matching can also be supported for embedding, as the following section is dedicated to.
Embed the same file as multiple variables
For example, in the following example, the s and s2 variables are embedded in the hello.txt file.
Exported/unexported variables are supported
Go can embed a file either as an exported variable or as an unexported variable.
Both package level variables and local variables are supported
The preceding examples are all package level variables, even if they are local variables within a function, and all support embedding.
The value of the local variable s is embedded at compile time, and although s and s2 are embedded in the same file, their values are compiled using different values in the initialization fields
|
|
Note that the values of the s and s2 variables are determined at compile time, so even if you change the hello.txt file at runtime, or even delete hello.txt, it will not change or affect the values of s and s2.
Read Only
The contents of the embedding are read-only. That is, whatever is embedded in the file at compile time is also what is embedded at runtime.
The FS file system value provides open and read methods, and no write method, which means that the FS instance is thread-safe and multiple goroutines can be used concurrently.
go:embed command
1, The go:embed command supports embedding multiple files
Of course you can also write it as a multi-line go:embed
like the previous example:
2, Folder support
The folder separator uses a forward slash /, even for windows systems.
3, Relative paths are used
The root path of the relative path is the folder where the go source file is located.
Support for applying double quotes"
or backquotes to embedded file or folder names or schema names, which is useful for files and folders with spaces or special characters in their names.
4, Matching mode
The go:embed
command allows you to write only the folder name, and all files and folders in this folder except for the .
and _
will be embedded, and subfolders will be recursively embedded, forming a file system for this folder.
If you want to embed files and folders starting with .
and _
files and folders, such as the .hello.txt file in the p folder, then you need to use *
, for example go:embed p/*
.
*
is not recursive, so subfolders under .
and _
will not be embedded unless you are embedding specifically using the *
of the subfolder:
Embed and embed mode do not support absolute paths, paths containing .
and ..
If you want to embed the path where the go source file is located, use *
:
File System
embed.FS implements the io/fs.FS
interface, which opens a file and returns fs.File
:
It also provides ReadFileh
and ReadDir
functions, traversing the information of files and folders under a file.
Since it implements the io/fs.FS
interface, it can return its subfolders as a new filesystem:
Applications
1, net/http
Previously, when we served a static file, we used.
|
|
Now, io/fs.FS
file system can also be converted to http.FileServer parameters:
So, the embedded file can be used in the following way:
|
|
2, text/template and html/template.
Similarly, templates can be parsed from the embedded file system.
Reference https://colobu.com/2021/01/17/go-embed-tutorial/