嵌入资源必须通过 embed.fs 读取且路径须为字面量、相对声明文件目录、大小写敏感,空目录及点下划线开头文件默认不嵌入;判断缺失需用 errors.is(err, fs.errnotexist)。

嵌入的资源必须通过 embed.FS 实例读取,不能用 os.Open 或 ioutil.ReadFile 等传统文件 API——那些会直接报 no such file or directory。
embed.FS.ReadFile 只接受字面量路径
你不能把路径拼成变量再传进去,fs.ReadFile 的第二个参数必须是字符串字面量(比如 "config.json"),否则编译失败或运行时 panic。
-
fs.ReadFile("assets/config.json")✅ 正确 -
fs.ReadFile(filepath.Join("assets", "config.json"))❌ 编译报错:go:embed cannot embed variable -
fs.ReadFile(dir + "/config.json")❌ 同上,变量拼接不被允许
路径必须相对于当前 .go 文件所在目录
不是项目根、不是 main.go 所在位置、也不是模块根,就是声明 //go:embed 的那个 .go 文件的目录。
- 如果你的文件在
cmd/myapp/main.go,想嵌入assets/logo.png,那assets/必须和main.go在同一级目录下 - 写
//go:embed assets/logo.png,读的时候也必须用fs.ReadFile("assets/logo.png"),不能省略assets/ -
//go:embed ./assets/logo.png❌ 会报错:不支持./前缀
读取失败时用 fs.ErrNotExist 判断
embed.FS 返回的是 *fs.PathError,不是传统的 os.IsNotExist 那套逻辑,用错就永远判不准。
-
if errors.Is(err, fs.ErrNotExist)✅ 正确 -
if os.IsNotExist(err)❌ 总是返回 false -
if err == fs.ErrNotExist❌ 不可靠,因为它是指针类型,应使用errors.Is
嵌入目录后,子路径必须完整写出
比如用 //go:embed assets/** 嵌入整个 assets/ 目录树,那 assets/css/style.css 就得原样写进 ReadFile,不能只写 css/style.css。
-
fs.ReadFile("assets/css/style.css")✅ -
fs.ReadFile("css/style.css")❌ 报file does not exist - 如果想简化前缀,先用
fs.Sub(fs, "assets")切出子树,再读css/style.css
最容易被忽略的是:嵌入路径大小写敏感,且空目录、以 . 或 _ 开头的文件默认不被包含——改名或加占位文件才能进二进制。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!











