gopkg.in/yaml.v3 是golang中最常用的yaml工具包,用此包解析yaml文件到结构体存在三个问题。

  1. yaml文件中的配置项首字母不能大写,配置项名字要求比较严格。
  2. 没有默认值。
  3. 没有数值校验。
解决思路
  1. 把yaml文件解析成map对象在通过json转成struct,利用json的的特性来控制yaml文件中字段名字。
  2. 通过https://github.com/creasty/defaults 这个工具添加默认配置。
  3. 通过https://github.com/dealancer/validate 这个工具添加校验。
    站在巨人肩上干活就是好又快。
代码实现

import (
 "encoding/json"
 "io/ioutil"
 "reflect"
 "github.com/creasty/defaults"
 "gopkg.in/dealancer/validate.v2"
 "gopkg.in/yaml.v3"
)
type YamlConfig struct {
 mapdata map[string]interface{}
 cfg interface{} //指针类型
}
func NewYamlConfig(cfg interface{}) (*YamlConfig, error) {
 rfv := reflect.ValueOf(cfg)
 if err := ValidatePtr(&rfv); err != nil {
 return nil, err
 }
 return &YamlConfig{cfg: cfg}, nil
}
// read and yaml unmarshal
func (this *YamlConfig) read(in string) error {
 bytes, err := ioutil.ReadFile(in)
 if err != nil {
 return err
 }
 if err := yaml.Unmarshal(bytes, &this.mapdata); err != nil {
 return err
 }
 return nil
}
// json to config obj
// use json tag not yaml
func (this *YamlConfig) jsonDecode() error {
 bytes, err := json.Marshal(this.mapdata)
 if err != nil {
 return err
 }
 // fmt.Println(string(bt), err)
 if err := json.Unmarshal(bytes, this.cfg); err != nil {
 return err
 }
 return nil
}
func (this *YamlConfig) doDefault() error {
 return defaults.Set(this.cfg)
}
func (this *YamlConfig) doValide() error {
 return validate.Validate(this.cfg)
}
func Load(configFile string, in interface{}) error {
 cfg, err := NewYamlConfig(in)
 if err != nil {
 return err
 }
 if err := cfg.read(configFile); err != nil {
 return err
 }
 if err := cfg.jsonDecode(); err != nil {
 return err
 }
 if err := cfg.doDefault(); err != nil {
 return err
 }
 if err := cfg.doValide(); err != nil {
 return err
 }
 return nil
}