跳到主要内容

go:embed 指令

· 阅读需 3 分钟

[GoLang官方提案]https://go.googlesource.com/proposal/+/master/design/draft-embed.md

//go:embed 支持嵌入静态文件。

  1. 对于单个文件,可以嵌入为字符串和 byte slice
  2. 多个文件,支持嵌入为新的文件系统 FS
  3. 只支持嵌入为string, byte sliceembed.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)
}))