golang使用viper加载配置文件实现自动反序列化到结构
作者:莫大
正文
- golang使用 viper 无需设置 mapstructure tag 根据配置文件后缀 自动返序列化到结构
- 解决结构有下划线的字段解析不成功问题
viper 正常加载配置文件
golang viper 其中可以用来 查找、加载和反序列化JSON、TOML、YAML、HCL、INI、envfile和格式的配置文件
配置文件 test_toml.toml
http_addr = ":8082" grpc_addr = ":8083" jaeger_url= "http://localhost:14268/api/traces" tracing= true
golang代码
type ConfigTest struct { HttpAddr string `json:"http_addr" toml:"http_addr" yaml:"http_addr"` GrpcAddr string `json:"grpc_addr" toml:"grpc_addr" yaml:"grpc_addr"` JaegerUrl string `json:"jaeger_url" toml:"jaeger_url" yaml:"jaeger_url" mapstructure:"jaeger_url"` Tracing bool `toml:"tracing" json:"tracing" yaml:"tracing" ` // opentelemetry tracing } // jaeger 加载配置文件 func TestSourceFile_Unmarshal(t *testing.T) { filePath := "./test_toml.toml" viper.SetConfigFile(filePath) if err := viper.ReadInConfig(); err != nil { t.Error(err) } c := &ConfigTest{} if err := viper.Unmarshal(c); err != nil { t.Error(err) } logger.Infow("Unmarshal file sucess", "v", c) }
打印返序列化的配置结构
{"level":"info","ts":"2023-08-27T21:35:27.041+0800","caller":"config/source_file_test.go:31","msg":"Unmarshal file sucess","v":{"http_addr":"","grpc_addr":"","jaeger_url":"http://localhost:14268/api/traces","tracing":true}}
可以看到带下划线的字段,不加 mapstructure 标签,是不会反序列化
不加 mapstructure tag实现自动反序列化
查看viper Unmarshal 代码
func (v *Viper) Unmarshal(rawVal interface{}, opts ...DecoderConfigOption) error { return decode(v.AllSettings(), defaultDecoderConfig(rawVal, opts...)) } func decode(input interface{}, config *mapstructure.DecoderConfig) error { decoder, err := mapstructure.NewDecoder(config) if err != nil { return err } return decoder.Decode(input) } func NewDecoder(config *DecoderConfig) (*Decoder, error) { if config.TagName == "" { config.TagName = "mapstructure" } // ... }
- 从代码看出 Viper使用的是 github.com/mitchellh/mapstructure来解析值
- mapstructure 用于将通用的map[string]interface{}解码到对应的 Go 结构体中
- 默认情况下,mapstructure 使用结构体中字段的名称做这个映射,不区分大小写,比如 Name 字段可以映射到 name、NAME、NaMe 等等
- 如果没有指定 tagName ,则默认为 mapstructure,这也是为什么带下划线的字段不加 mapstructure 标签无法解析的原因
- viper 中Unmarshal的第二个参数是可以指定 DecoderConfigOption ,从而可以指定 tagName
viper根据文类型件自动解码到结构
- 读取文件后缀比如 toml
- 根据后缀设置 tagName
- 调用 viper.Unmarshal解析
func TestSourceFile_Unmarshal1(t *testing.T) { filePath := "./test_toml.toml" c := &ConfigTest{} if err := viperUnmarshal(c, filePath); err != nil { t.Error(err) } logger.Infow("Unmarshal file sucess", "v", c) } func viperUnmarshal(v interface{}, configPath string) error { var tagName string ext := filepath.Ext(configPath) if len(ext) > 1 { tagName = ext[1:] } // set decode tag_name, default is mapstructure decoderConfigOption := func(c *mapstructure.DecoderConfig) { c.TagName = tagName } cViper := viper.New() cViper.SetConfigFile(configPath) if err := cViper.ReadInConfig(); err != nil { return err } return cViper.Unmarshal(v, decoderConfigOption) }
结果:
{"level":"info","ts":"2023-08-27T21:35:34.553+0800","caller":"config/source_file_test.go:40","msg":"Unmarshal file sucess","v":{"http_addr":":8082","grpc_addr":":8083","jaeger_url":"http://localhost:14268/api/traces","tracing":true}}
我已将viper加载配置集成进自己的项目,完整example 代码可以查看 source_file_test.go
以上就是golang 使用 viper 加载配置文件 自动反序列化到结构的详细内容,更多关于golang viper 加载配置文件 自动反序列化到结构的资料请关注脚本之家其它相关文章!