go embed
embed 是 Go 1.16 引入的一项功能,用于将文件或文件夹嵌入到 Go 程序中。在编译时,Go 编译器会把这些文件的内容嵌入到生成的二进制文件中,这样就可以在不依赖外部文件的情况下运行应用程序。常用于嵌入配置文件、HTML 模板、静态资源等。
1. 使用 embed 嵌入单个文件
要使用 embed,需要在 Go 文件中使用 //go:embed 注释来指定要嵌入的文件,然后通过变量来访问这些文件的内容。
示例:嵌入一个单独的 config.yaml 文件
步骤:
- 在你的 Go 文件中使用
//go:embed来嵌入文件。 - 使用
var变量来接收嵌入的内容。
示例代码
假设你有一个 config.yaml 文件,内容如下:
yaml
app_name: MyApp
version: 1.0你可以这样在 Go 程序中嵌入该文件:
go
// main.go
package main
import (
_ "embed"
"fmt"
"log"
"gopkg.in/yaml.v2"
)
//go:embed config.yaml
var configData []byte
type Config struct {
AppName string `yaml:"app_name"`
Version string `yaml:"version"`
}
func main() {
// 解码嵌入的 YAML 内容
var config Config
err := yaml.Unmarshal(configData, &config)
if err != nil {
log.Fatal(err)
}
// 输出解析后的内容
fmt.Printf("App Name: %s, Version: %s\n", config.AppName, config.Version)
}说明:
//go:embed config.yaml告诉 Go 将config.yaml文件的内容嵌入到configData变量中。var configData []byte用于存储嵌入的文件内容,这里是以字节切片的形式存储 YAML 文件内容。- 使用
yaml.Unmarshal将字节数据反序列化为结构体。
2. 嵌入多个文件
你也可以嵌入多个文件或整个文件夹。
示例:嵌入多个文件
假设你有两个配置文件:config.yaml 和 another_config.yaml,你可以这样嵌入它们:
go
//go:embed config.yaml another_config.yaml
var configFiles embed.FS这里使用 embed.FS 类型来存储文件系统,允许你按需读取嵌入的文件。
示例代码:
go
// main.go
package main
import (
"embed"
"fmt"
"io/fs"
"log"
"gopkg.in/yaml.v2"
)
//go:embed config.yaml another_config.yaml
var configFiles embed.FS
type Config struct {
AppName string `yaml:"app_name"`
Version string `yaml:"version"`
}
func main() {
// 读取嵌入的文件
data, err := fs.ReadFile(configFiles, "config.yaml")
if err != nil {
log.Fatal(err)
}
var config Config
err = yaml.Unmarshal(data, &config)
if err != nil {
log.Fatal(err)
}
// 输出解析后的内容
fmt.Printf("App Name: %s, Version: %s\n", config.AppName, config.Version)
// 读取另一个配置文件
anotherData, err := fs.ReadFile(configFiles, "another_config.yaml")
if err != nil {
log.Fatal(err)
}
fmt.Println("Another Config File Contents:")
fmt.Println(string(anotherData))
}说明:
//go:embed config.yaml another_config.yaml告诉 Go 将config.yaml和another_config.yaml两个文件的内容嵌入到configFiles变量中,configFiles是一个embed.FS类型的文件系统对象。- 使用
fs.ReadFile(configFiles, "config.yaml")来读取嵌入的文件内容。
3. 嵌入整个文件夹
你也可以将整个文件夹嵌入到 Go 程序中,这在需要嵌入大量资源文件时非常有用。
示例:嵌入一个文件夹
假设你有一个 assets 文件夹,包含多个文件,想要将整个文件夹嵌入到程序中:
go
//go:embed assets/*
var assets embed.FS示例代码:
go
// main.go
package main
import (
"embed"
"fmt"
"io/fs"
"log"
)
//go:embed assets/*
var assets embed.FS
func main() {
// 读取嵌入的文件夹中的某个文件
data, err := fs.ReadFile(assets, "assets/config.yaml")
if err != nil {
log.Fatal(err)
}
// 打印文件内容
fmt.Println(string(data))
}说明:
//go:embed assets/*将整个assets文件夹中的所有文件嵌入到assets变量中,assets是一个embed.FS类型的文件系统对象。- 使用
fs.ReadFile(assets, "assets/config.yaml")来读取嵌入的assets/config.yaml文件。
4. 嵌入二进制文件
embed 还可以用于嵌入二进制文件,如图片、音频文件等。你可以像处理文本文件一样处理二进制数据。
示例:嵌入图片文件
假设你要嵌入一个图片文件 logo.png:
go
//go:embed logo.png
var logo []byte然后,你可以在应用中使用这个 logo 字节数据来做一些处理,比如将其输出到一个 Web 页面上,或者保存到磁盘。
5. 限制与注意事项
embed只支持嵌入 Go 源文件所在目录下的文件,不能跨目录。- 嵌入的文件内容在编译时确定,因此需要重新编译程序才能更新文件内容。
embed.FS提供了一些文件操作方法,如ReadFile,可以像操作普通文件系统一样访问嵌入的文件。
总结
embed是 Go 1.16 引入的强大功能,允许将文件嵌入到二进制中。- 使用
//go:embed注释来指定要嵌入的文件或文件夹。 - 使用
embed.FS来操作嵌入的文件,支持按文件读取。 - 适用于配置文件、模板、静态资源等的打包和分发。