项目场景:
go-zero
作为框架开发,使用他原生的解析方法进行配置解析
问题描述
添加自己定义的配置
发现解析不正确:
这是我的配置文件,自己添加了一个数据库的配置
type TDengineSetting struct {
Server string `yaml:"server"` //TDengine服务地址
UserName string `yaml:"user_name"` //用户名
Password string `yaml:"password"` //密码
Port int32 `yaml:"port"` //端口
ConnectionType string `yaml:"connection_type"` //连接类型,原生或者restful
DbName string `yaml:"db_name"`
}
这是我的解析,这样来看完全没问题,yaml是对得上的
原因分析:
首先我们要知道go-zero的解析在哪里进行。代码是这个:
conf.MustLoad(*configFile, &config.GlobalConfig)
然后我们一步一步点进去看里面的逻辑,看
MustLoad方法
// MustLoad loads config into v from path, exits on error.
func MustLoad(path string, v interface{}, opts ...Option) {
if err := Load(path, v, opts...); err != nil {
log.Fatalf("error: config file %s, %s", path, err.Error())
}
}
就一个Load函数在里面,继续下一步,看
Load
// Load loads config into v from file, .json, .yaml and .yml are acceptable.
func Load(file string, v interface{}, opts ...Option) error {
content, err := os.ReadFile(file)
if err != nil {
return err
}
loader, ok := loaders[strings.ToLower(path.Ext(file))]
if !ok {
return fmt.Errorf("unrecognized file type: %s", file)
}
var opt options
for _, o := range opts {
o(&opt)
}
if opt.env {
return loader([]byte(os.ExpandEnv(string(content))), v)
}
return loader(content, v)
}
最后两步他执行了loader函数,但是是函数回调,回调前他是通过loadersMap进行赋值的,进去
loaders
看看
var loaders = map[string]func([]byte, interface{}) error{
".json": LoadFromJsonBytes,
".toml": LoadFromTomlBytes,
".yaml": LoadFromYamlBytes,
".yml": LoadFromYamlBytes,
}
差不多要浮出水面了,我的是yaml文件,进去
LoadFromYamlBytes
看看
// LoadFromYamlBytes loads config into v from content yaml bytes.
func LoadFromYamlBytes(content []byte, v interface{}) error {
b, err := encoding.YamlToJson(content)
if err != nil {
return err
}
return LoadFromJsonBytes(b, v)
}
发现他是先
把yaml转成json
再调用LoadFromJsonBytes方法进行解析的,这不扯淡嘛,还是得回到json
,进去YamlToJson看看
func YamlToJson(data []byte) ([]byte, error) {
var val interface{}
if err := yaml.Unmarshal(data, &val); err != nil {
return nil, err
}
val = toStringKeyMap(val)
var buf bytes.Buffer
if err := json.NewEncoder(&buf).Encode(val); err != nil {
return nil, err
}
return buf.Bytes(), nil
}
这里就发现问题所在了,这里用
son.NewEncoder(&buf).Encode(val)
去序列化我的配置信息,但我的配置没有设置json标签的,他就会把json默认是标识符
,我的标识符全是大写开头
的,例如:Server; 但是我的配置文件写的yaml标签是小写开头
的,所以就出现了配置加载不上的问题
解决方案:
有两个解决办法
一、所有的配置都采用大写开头
,不用写yaml标签都能解析成功,作者使用的是这个方法
二、解析的结构体标签增加多一个json标签
,对应着yaml文件的配置,此方法不推荐,作者也没尝试过,如有问题,欢迎评论