比viper还好用的go语言配置库

74 阅读1分钟

起因

事情起因,公司想要考虑使用配置中心,在调研配置客户端时,看到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,完善这个库