go:embed 指令
[GoLang官方提案]https://go.googlesource.com/proposal/+/master/design/draft-embed.md
//go:embed
支持嵌入静态文件。
- 对于单个文件,可以嵌入为字符串和
byte slice
- 多个文件,支持嵌入为新的文件系统 FS
- 只支持嵌入为
string
,byte slice
和embed.FS
三种类型,这三种类型的别名(alias)和命名类型(如type S string)都不可以
嵌入字符串
//go:embed hello.txt
var s string
嵌入为 byte slice
//go:embed hello.txt
var b []byte
嵌入为fs.FS
基本使用
//go:embed hello.txt
var f embed.FS
支持同一变量上嵌入多个文件
//go:embed hello1.txt
//go:embed hello2.txt
var f embed.FS
func main() {
data, _ := f.ReadFile("hello.txt")
fmt.Println(string(data))
data, _ = f.ReadFile("hello2.txt")
fmt.Println(string(data))
}
匹配模式
go:embed dirpath
次文件夹下的除了 .
和 _
开头的文件/文件夹都会被嵌入(递归)。
如果要嵌入.
和_
开头的文件/文件夹,需要使用 go:embed dirpath/*
。
注意:这个只能嵌入 dirpath 目录下的 .
和_
开头的文件/文件夹。子文件夹下的 .
和 _
开头的文件/文件夹是不会嵌入。
使用
将前端静态文件打包进 go 程序
嵌入静态文件
//go:embed frontend/out/*
var buildFS embed.FS
输出日志,检查文件是否被正确嵌入
// 打印嵌入的文件系统内容,用于调试
fs.WalkDir(buildFS, ".", func(path string, d fs.DirEntry, err error) error {
if err != nil {
return err
}
if !d.IsDir() {
log.Printf("嵌入文件系统中有: %s", path)
}
return nil
})
静态文件服务
// 创建一个子文件系统,将嵌入的文件系统 buildFS 中的 frontend/out 目录作为新文件系统的根目录
contentFS, err := fs.Sub(buildFS, "frontend/out")
if err != nil {
log.Fatalf("无法获取嵌入的前端文件: %v", err)
}
// 创建一个文件服务处理器
fileServer := http.FileServer(http.FS(contentFS))
// 为所有路径提供服务
r.PathPrefix("/").Handler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
// 打印请求路径,帮助调试
log.Printf("请求文件: %s", r.URL.Path)
fileServer.ServeHTTP(w, r)
}))