结构体绑定必须显式声明所有mapstructure tag:嵌套字段不加tag即为空,即使字段名与yaml键一致;顶层字段可省略,但一旦存在嵌套(如database struct),其内部每个字段都须带mapstructure:"xxx";连字符键名(如max-connections)必须严格匹配;环境变量需配合setenvprefix与automaticenv;多环境应拆分配置文件而非硬编码if判断;热更新需在watch回调中重新unmarshal;敏感字段应留空并优先从环境变量读取。

结构体绑定必须显式声明所有 mapstructure tag
嵌套字段不加 mapstructure tag 就是空的,哪怕字段名和 YAML 键完全一致。Go 不会自动推导映射关系,viper.Unmarshal 或 mapstructure.Decode 都只认 tag。
- 顶层字段可省略 tag,但只要有一层嵌套(比如
Databasestruct),内部每个字段都得带mapstructure:"host"这类声明 - YAML 里写
max-connections: 10,结构体字段就得是MaxConnections int `mapstructure:"max-connections"`,不能写成"max_connections"或"MaxConnections" - 布尔值、数字类型字段如果 tag 写错或缺失,解码后就是零值,且无报错——静默失败比 panic 更难排查
多环境配置不能靠 if env == "prod" 分支硬切
把环境判断逻辑塞进业务代码,等于把部署细节污染到领域层。CI/CD 切换时容易漏改,本地调试也常因忘记设 ENV 环境变量而走错路径。
-
配置文件按环境拆分:
config.common.yaml(通用) +config.dev.yaml+config.prod.yaml - 启动时用
viper.SetConfigName(fmt.Sprintf("config.%s", env))加载,而不是在 handler 里写if os.Getenv("ENV") == "prod" - 开关类配置(如
server.enable_pprof)统一走 viper 读取,避免散落在各处的环境判断
热更新时 Unmarshal 必须在 Watch 回调里重执行
viper.WatchConfig() 只通知“配置变了”,不会自动刷新你已定义的结构体变量。常见错误是只注册回调却不调 viper.Unmarshal(&cfg),结果字段永远停留在初始值。
- 回调函数内必须传地址:
viper.Unmarshal(&cfg),不是viper.Unmarshal(cfg) - 确保结构体所有字段都是导出的(首字母大写),否则
Unmarshal直接跳过 - 如果用了
RWMutex保护配置指针,更新后要Lock()替换指针,再Unlock(),不能原地修改字段
敏感字段别混在配置文件里写明文
密码、密钥这类字段一旦提交到 Git,就很难彻底清理。即便用 .gitignore,历史记录里仍残留痕迹。
- 配置文件中留空或写占位符:
password: ""或password: "__PLACEHOLDER__" - 运行时优先从环境变量读:
os.Getenv("DB_PASSWORD"),仅当为空时才 fallback 到配置文件 - 若用 viper,务必配合
viper.SetEnvPrefix("APP")和viper.AutomaticEnv(),否则环境变量根本不会被映射
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!











