测试必须用os.CreateTemp动态创建临时YAML/JSON文件,传空字符串指定默认临时目录,写入后先Close再Remove;解析函数须接收路径参数而非硬编码;错误需包裹文件名上下文;结构体字段须导出并加yaml tag。

测试中用 os.CreateTemp 创建临时 YAML/JSON 文件
直接硬编码 ./test-config.yaml 会导致测试污染、CI 权限失败、并发冲突。必须用 os.CreateTemp 动态生成唯一路径文件。
关键操作顺序不能错:
- 调用
os.CreateTemp("", "config-*.yaml"),第一个参数传空字符串,让系统选默认临时目录 - 写入内容后立刻调用
file.Close()——否则os.ReadFile可能读不到最新数据 -
defer os.Remove(filepath)必须放在file.Close()之后,否则 Windows 下报“文件正被使用”
示例片段:
file, err := os.CreateTemp("", "config-*.yaml")
if err != nil {
t.Fatal(err)
}
defer file.Close()
_, _ = file.WriteString("port: 8080\nlog_level: debug")
defer os.Remove(file.Name()) // 注意:这里必须在 Close 之后
解析函数必须接收文件路径参数而非硬编码
如果函数内部写死 "./config.yaml" 或从环境变量读路径,就无法注入测试文件,等于不可测。
立即学习“go语言免费学习笔记(深入)”;
重构原则很明确:
- 旧函数保留为包装器:
func ParseConfig() (Config, error) { return ParseConfig("./config.yaml") } - 核心逻辑函数签名改为接收路径:
func ParseConfig(path string) (Config, error) - 调用时传入
file.Name(),确保测试与生产走同一代码路径
不这么做,所有配置解析逻辑都绕不开 “无法 mock 路径” 这个硬伤。
使用 uber-go/dig 在 Golang 中实现依赖注入——基于反射容器,提供 Provide/Invoke、dig.In/dig.Out 参数与结果对象,支持命名依赖等
YAML/JSON 解析失败时错误信息不带文件名上下文
yaml.Unmarshal 报错类似 line 5: cannot unmarshal !!str `abc` into int,但没说来自哪个文件——这对定位问题极其不利。
必须手动补全上下文:
- 不要直接返回
yaml.Unmarshal(data, &cfg)的 error - 封装一层:捕获 error 后用
fmt.Errorf("parse %s: %w", path, err)包裹 - 如果解析的是嵌套结构(如
database.host),建议在 error 中追加字段路径提示
这样出错时一眼看到是 test-config.yaml: line 5...,而不是翻日志查哪次测试跑的哪个文件。
结构体字段必须导出 + 显式 tag + 指针传参
常见 panic 全因反射调用姿势不对,不是配置内容错:
- 传
cfg给yaml.Unmarshal会静默失败;必须传&cfg - 字段名小写(如
port int)不会被解析,必须大写(Port int) - 嵌套结构体要加
yaml:",inline"才能平铺字段,否则解析为空
示例正确结构:
type Config struct {
Port int `yaml:"port"`
DB DBConf `yaml:"database"`
}
type DBConf struct {
Host string `yaml:"host"`
}
解析时:err := yaml.Unmarshal(data, &cfg) —— 少一个 & 或少一个大写,就白忙活。

















