Go-Zero默认只加载etc/config.yaml,不自动识别环境变量;需手动拼接路径(如etc/config.dev.yaml)或通过命令行参数指定配置文件,且多环境覆盖需自行实现字段级合并。

Go-Zero项目启动时,配置文件加载顺序直接影响服务能否正确读取dev、test、prod等环境参数,顺序错乱会导致本地调试连上生产数据库或功能开关失效。
Go-Zero默认配置加载逻辑
go-zero框架不依赖Viper,而是使用自身封装的conf包加载配置。它默认只加载etc/config.yaml一个文件,且不会自动识别环境变量或拼接后缀。这意味着即使你设置了APP_ENV=dev,程序仍会去读etc/config.yaml,而非etc/config.dev.yaml。
这一步操作起来很简单,直接把文件拖进去就行。
若未显式指定其他路径,conf.MustLoad()将严格按字面路径查找,找不到就panic,不尝试fallback或自动补全。
手动实现多环境配置加载
必须在main函数中主动构造带环境标识的文件路径,再传给conf.MustLoad()。这是唯一可靠的方式。
方法一:用os.Getenv动态拼接文件名
第一步:获取环境变量值,推荐统一用小写避免大小写敏感问题:env := strings.ToLower(os.Getenv("ENV"))
第二步:构造完整路径:configPath := fmt.Sprintf("etc/config.%s.yaml", env)
第三步:调用加载:conf.MustLoad(configPath, &c)
注意:configPath必须是相对或绝对路径,不能只写config.dev.yaml——conf.MustLoad不支持自动补前缀或后缀。
方法二:通过命令行参数传入配置路径
启动时指定:./service -f etc/config.test.yaml
代码中接收:flag.StringVar(&configFile, "f", "etc/config.yaml", "the config file")
然后conf.MustLoad(configFile, &c)
方法三:结合goctl生成的配置结构体,在init中预设路径
在config.go顶部添加:var ConfigFile = os.Getenv("CONFIG_FILE")
若为空则fallback到"etc/config.yaml",但不建议fallback到硬编码路径,否则dev环境误用prod配置的风险极高。
配置项覆盖优先级规则
go-zero本身不提供多源配置合并机制(如命令行>环境变量>文件),所有配置必须由单一YAML文件提供。若需分层覆盖,必须由开发者自行实现:
先加载基础配置文件(如etc/config.base.yaml)→ 再加载环境专属文件(如etc/config.prod.yaml)→ 使用mapstructure或gjson做字段级merge → 最后注入结构体。
这一步容易踩坑:两个YAML里同名字段(如log.level),后加载的会完全覆盖前者,不会做深度合并。例如base里log: {level: info, path: ./logs},prod里只写log: {level: error},最终log.path会丢失。
敏感字段如db.password、redis.auth严禁出现在任何YAML中,必须通过环境变量注入,并在结构体tag中标记env:"DB_PASSWORD",再用os.Getenv读取后手动赋值。











