在 Go 里定义 struct 及其序列化&反序列化的方式都是通过 Tag 的方式做的, 但是在我开始使用 Apollo 的时候没有找到社区的解决方案,所以翻了下 BSON/JSON/YAML 的反序列化实现方式, 觉得用反射机制好像是可以做的,于是就开搞了,项目在 https://github.com/caiyunapp/oap

用法如下:

定义一个结构体,声明了在 Apollo 配置中心的字段名称,通过 , 分割定义嵌入的 strcut 反序列化方式。

type DemoConfig struct {
	Foo          string  `apollo:"foo"`
	Hello        string  `apollo:"hello"`
	Float32Field float32 `apollo:"float32Field"`
	Float64Field float32 `apollo:"float64Field"`
	BoolField    bool    `apollo:"boolField"`
	Substruct    struct {
		X string `json:"x"`
		Y int    `json:"y"`
	} `apollo:"substruct,json"`
	SubstructFromYAML struct {
		X string `yaml:"x"`
		Y int    `yaml:"y"`
	} `apollo:"substructFromYAML,yaml"`
}

然后初始化客户端后调用即可:

conf := &DemoConfig{}
if err := oap.Decode(conf, client, make(map[string][]agollo.OpOption)); err != nil {
	panic(err)
}

需要注意的是这个包显示依赖了 philchia/agollo 的 Apollo 客户端实现。 原因是其他的 Apollo Go 客户端实现依赖了 Viper 做配置的序列化, 但是对应的功能实现用不上,所以在 go.sum 里引入几百行依赖有些闹心。 只有这个实现是完全独立的,没有引入太多用不到的东西。

写本文的时候发现 GitHub 上有个项目实现了类似的事情 https://github.com/tagconfig/tagconfig 只是更加复杂一些,其实更符合直觉,会自动处理层级的 Tag 名称。