起因
事情起因,公司想要考虑使用配置中心,在调研配置客户端时,看到viper支持远程配置获取,然后研究了一下怎么使用(可以看下我上篇文章),在使用过程中发现如果,Watch到配置变化,返回的数据会被viper合并到kvstore中,如果合并时有正在读配置的地方就会造成panic,这对我们的服务来说是致命的。
后面我在github上fork了一个viper分支,改好后提了一个pr,好几周都没有一个人回复,没人review,在issue上也发现别人在很久之前就提过这个问题,但是官方没有任何想要解决的意思。没办法,我们自己动手搞一个吧!
自认为比viper好用 🐶
看下例子:
配置文件长这样
httpPort: 8080
grpcPort: 9090
worker:
name: "worker1"
maxWorkers: 10
maxIdleWorkers: 10
maxQueueSize: 100
workerWeight:
- 1
- 1
- 10
go文件长这样
package main
import (
"log"
"github.com/shifengbin/doggie"
)
type Worker struct {
Name string
MaxWorkers int
MaxIdleWorkers int
MaxQueueSize int
WorkerWeight []int
}
type NamedWorker struct {
A string `doggie:"name"`
B int `doggie:"maxWorkers"`
C int `doggie:"maxIdleWorkers"`
D int `doggie:"maxQueueSize"`
E []float32 `doggie:"workerWeight"`
}
func main() {
dog := doggie.New()
dog.SetConfigFile("./app.yaml")
dog.ReadConfig()
//直接获取配置
log.Println("httpPort", dog.Get("httpPort").Int())
log.Println("grpcPort", dog.Get("httpPort").Int())
//通过默认规则获取
worker := Worker{}
dog.Get("worker").Unmarshal(&worker)
log.Println(worker)
//通过tag获取
named := NamedWorker{}
dog.Get("worker").Unmarshal(&named)
log.Println(named)
//直接获取多级
weight := dog.Get("worker.workerWeight")
for i := 0; i < weight.Len(); i++ {
log.Println("wight", i, weight.Idx(i).Int())
}
//直接遍历对象类型
w := dog.Get("worker")
keys := w.Keys()
for _, key := range keys {
log.Println(key, w.Get(key).String())
}
}
可以看到,数据类型转换很方便,也有对应的unmarshal方法可以转换成结构体,更多例子可以参考项目的example目录
大家喜欢这种方式的可以试用,欢迎大家一起讨论,提pr,完善这个库