go viper库读取配置文件,复合名词字段读取不到值

提示:多个单词组合在一起可以构成了一个复合名词(compound noun)


前言

提示:如果出现这个错误看一下这两句话就可以了,不用往下看了[doge]

问题:使用viper读取YAML配置文件的时候,当一个字段由多个单词组成的时候(比如YAML配置文件里面jwt的secret_key字段),读取不到值

解决方法:viper推荐使用mapstructure标签进行映射,即项目中配置结构体的字段使用mapstructure标签进行映射


提示:以下是本篇文章正文内容,下面案例可供参考

一、从出现问题到找到问题根源

下面是一个极其简陋的YAML配置文件,位于项目根目录下

(标注:秘钥是拿来测试用的,等会再随机生成一个,所以是不存在泄露问题的[doge])

settings.yaml

mysql:
  host: 127.0.0.1
  port: 3306
  user: root
  password: 123456
  dbname: gvb_db

redis:
  host: 127.0.0.1
  port: 6379
  password:

system:
  host: 0.0.0.0
  port: 8190
  env: dev

log:
  level: info
  filename: logs/app.log
  max_size: 100
  max_backups: 5
  max_age: 7
  compress: true

jwt:
  secret_key: b08f2e537d494dee0f044e6c69ec7b24c6e68f6c5e4e2783a0774277bc343515  # 替换为你的密钥
  expiration: 24h # 令牌过期时间,这里是24小时

core/config.go

func LoadConfig() (*config.Config, error) {
	viper.SetConfigName("settings") // name of config file (without extension)
	viper.AddConfigPath(".")       // optionally look for config in the working directory
	err := viper.ReadInConfig()    // Find and read the config file
	if err != nil {
		return nil, fmt.Errorf("failed to read config: %w", err)
	}
    // 下面四行代码仅限于测试使用,第一行是打印文件路径,第二行是打印所有键值,第三四行是测试能否读到jwt的配置
	fmt.Println("Config loaded:", viper.ConfigFileUsed())
	fmt.Println("Config loaded:", viper.AllKeys())
	fmt.Println("Config loaded:", viper.GetString("jwt.expiration"))
	fmt.Println("Config loaded:", viper.GetString("jwt.secret_key"))
    
	var cfg config.Config
	err = viper.Unmarshal(&cfg)
	if err != nil {
		return nil, fmt.Errorf("failed to unmarshal config: %w", err)
	}

	return &cfg, nil
}

出现问题的时候(即使用viper读取YAML配置文件的时候,当一个字段由多个单词组成的时候(比如YAML配置文件里面jwt的secret_key字段),读取不到)

我使用fmt.Println("Config loaded:", viper.AllKeys())发现viper.ReadInConfig() 已经读取了所有的配置键了,如下图,数组里面的即为键

在这里插入图片描述

同时以下代码均打印了键对应的值

fmt.Println("Config loaded:", viper.GetString("jwt.expiration"))
fmt.Println("Config loaded:", viper.GetString("jwt.secret_key"))

如下图

在这里插入图片描述

所以问题出现在了viper将配置映射到项目的config结构体的时候出错了

err = viper.Unmarshal(&cfg)这一句代码出错啦

二、以下是问题处理的全过程

以下是问题处理的全过程:

问题:使用viper读取配置文件的时候,当一个字段由多个单词组成的时候(比如YAML配置文件里面jwt的secret_key字段),读取不到值,

原因:代码err = viper.Unmarshal(&cfg)出现问题,即,将配置文件映射到配置结构体中,复合名词字段映射失败,无法得到值

  • 查看版本号,go list -m github.com/spf13/viper
    • 更新版本 go get -u github.com/spf13/viper,发现还是读取不到值。通过更新解决bug的方法失败,此路不通
  • 更换配置文件,将YAML配置文件更换为TOML配置文件
    • golang应用中对该JWT配置的引用都与我的settings.yaml文件保持一致的,即结构体字段使用将标签yaml改为标签toml
    • 发现还是读取不到值。通过更换配置文件的方法失败,此路不通
  • 更改复合名词的格式
    • _间隔更改为-,即secret_key更改为secret-key,结构体标签yaml里面的值也跟着同步。结果失败,没有读取到值
    • 同理,更改为小驼峰和大驼峰命名法,结构体标签yaml里面的值也跟着同步。结果失败,没有读取到值。更改复合名词的格式的方法失败。
  • 后面发现viper推荐使用mapstructure标签进行映射
    • golang应用中对该JWT配置的引用,即结构体字段使用将标签mapstructure即可
    • 成功读取到值!使用mapstructure标签进行映射的方法成功,撒花!

现在解决了,通过项目中配置结构体里面字段的标签添加上mapstructure标签即可

下面是有问题的代码

type JWTConfig struct {
	Secret     string `yaml:"secretKey"`  // 密钥
	Expiration string `yaml:"expiration"` // 过期时间
}

将上面代码添加上mapstructure标签即可,当然,项目配置结构体的标签一般要一致,所以我所有的配置结构体字段都添加上了,已经在改了,在改了,还好不多哈哈

type JWTConfig struct {
	Secret     string `yaml:"secret_key" mapstructure:"secret_key"` // 密钥
	Expiration string `yaml:"expiration"`                          // 过期时间
}

总结

viper推荐使用mapstructure标签进行映射,即项目中配置结构体的字段使用mapstructure标签进行映射,其他标签也能映射,但容易出现问题。

  • 10
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值