viper包加载蛇形字段配置失败

问题

今天在使用 github.com/spf13/viper 加载配置文件时突然发现有几个字段的值始终无法正常加载,大致形如

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
type Config struct {
Name string `yaml:"name"`
UserId int `yaml:"user_id"`
}

func GetSnakeValue() Config {
v := viper.New()
v.Set("user_id", 1)
v.Set("name", "victor")
var cfg Config
err := v.Unmarshal(&cfg)
if err != nil {
panic(err)
}
return cfg
}

执行结果如下:

1
2
3
4
Config{
Name: "victor",
UserId: 0
}

明显不符合预期:

1
2
3
4
Config{
Name: "victor",
UserId: 1
}

现象分析

  1. Config.Name 可以正常加载,那说明 viper 正常工作了
  2. 在断点中可以看到 user_id 正常加载,继续断点下去是一些反射代码,没法直观分析
  3. Config.UserId 无法正常加载,那么说明在decode时失败

根据网上资料得知,viper.Unmarshal 底层其实是用 mapstructure.Decode,但它对 tag、key 的处理有自己的默认行为:

  • 会把所有 key 转换成 小写
  • 默认不会启用 WeaklyTypedInputSquash 等高级选项。
  • 不会自动启用驼峰 → 下划线的映射。

解决方案

知道了原因,那么就可以按图索骥。

  1. 将tag的value改为驼峰写法,userId这样就可以正常解析

  2. 添加mapstructure tag 让mapstructure.Decode知道 user_id对应的 struct field,如:

    1
    2
    3
    4
    type Config struct {
    Name string `yaml:"name"`
    UserId int `yaml:"user_id" mapstructure:"user_id"`
    }
  3. 在调用func (v *Viper) Unmarshal(rawVal any, opts ...DecoderConfigOption) error时,设置DecoderConfigOption


viper包加载蛇形字段配置失败
https://fatwang1.github.io/2025/09/07/2025090700/
作者
衣云乘风
发布于
2025年9月7日
许可协议