Doggie是一个配置管理工具,支持多种配置源,支持多种配置格式,支持多种配置读取方式,支持多种配置监控方式
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())
}
//解码一个切片
var uints []uint
if err := dog.Get("worker.workerWeight").Unmarshal(&uints); err != nil {
log.Println(err)
}
log.Println(uints)
}
其他可参考example文件夹的例子
配置读取: 1.读取文件配置 2.读取远程配置 3.读取环境变量
编码: 1.自定义解码方法 2.内置解码
监控: 1.文件监控 2.自定义监控方法(远程)
查找顺序: 1. 命令行参数 2. 环境变量 3. 配置文件 4. 远程配置 5. 默认值
其他: 1.设置默认值
注意:
自定义解码器转换的数据结构应为map[string]interface{}, 数组需要满足[]interface{}类型
如何实现远程配置,请参考example/remote.go
不提供:
写配置文件,应用程序不应修改配置文件
别名,别名会影响程序的维护,在程序中到处改key会导致无法与配置文件对应,难以理解和维护
通过Get方法获取转换器Caster, Caster负责转换数据和Unmarshal数据
- RegisterDecoder 注册自定义解码器
- SetConfigFile 设置配置文件
- SetFileType 设置配置文件类型,用于解码,如果不设置则通过SetConfigFile设置文件的扩展名获取
- SetRemoteType 设置远程配置文件类型,用于解码
- SetRemoteProvider 设置远程配置提供者
- SetDefault 设置默认值
- ReadConfig 读取配置文件,配置好上述设置后,需要调用该函数进行配置文件读取
- WatchConfig 监控文件和远程配置变换,没有配置则不会监控对应类型配置
- GetEnv() Caster 从环境变量中获取配置
- GetConfig() Caster 从配置文件中获取配置
- GetRemoteConfig() Caster 从远程配置中获取配置
- GetFlag() Caster 获取命令行参数配置
- Get() Caster 获取配置项,通过优先级顺序获取flag > env > config > remote > default
- Int() 把值转换为int
- Int8() 把值转换为int8
- Int16() 把值转换为int16
- Int32() 把值转换为int32
- Int64() 把值转换为int64
- Uint() 把值转换为uint
- Uint8() 把值转换为uint8
- Uint16() 把值转换为uint16
- Uint32() 把值转换为uint32
- Uint64() 把值转换为uint64
- String() 把值转换为string
- Bool() 把值转换为bool
- Float32() 把值转换为float32
- Float64() 把值转换为float64
- Keys() 获取map key
- Get(key string) Caster 获取map key对应的值
- Unmarshal(obj interface{}) error 把值转换为struct
- Len() 获取map或者slice的length
- Idx(idx int) Caster 获取slice对应值
支持格式:
- -a
- -a 10
- -a=10
- --a
- --a 10
- --a=10
读取系统环境变量
//创建配置实例
dog := doggie.New()
//设置文件路径
dog.SetConfigFile("./testdata/a.yml")
//读取配置
dog.ReadConfig()
//获取配置项
if v := dog.Get("a").Int(); v != 10 {
t.Log("Get a Want 10, but:", v)
t.Fail()
}
//d.e是一个数组,可以通过.Idx获取下标对应的值
if vv := v.Get("d.e").Idx(1).Int(); vv != 2 {
t.Log("Get d.e[1] Want 2, but:", vv)
t.Fail()
}
创建远程配置提供者
type HttpProvider struct {
URL string
}
func (h HttpProvider) SetUp() ([]byte, error) {
f, err := os.Open("../testdata/real.json")
if err != nil {
return nil, err
}
defer f.Close()
return io.ReadAll(f)
}
type Config struct {
A int `json:"a"`
B string `json:"b"`
D struct {
E []int `json:"e"`
} `json:"d"`
}
func (h HttpProvider) Watch() ([]byte, error) {
// time.Sleep(2 * time.Second)
data, err := h.SetUp()
if err != nil {
return nil, err
}
c := Config{}
if err := json.Unmarshal(data, &c); err != nil {
return nil, err
}
c.D.E = append(c.D.E, int(time.Now().Unix()))
return json.Marshal(c)
}
func NewHttpProvider(url string) *HttpProvider {
return &HttpProvider{
URL: url,
}
}
注册到配置中
provider := NewHttpProvider("http://aabb.com/aa")
dog := doggie.New()
dog.SetRemoteProvider(provider, false)
// dog.SetConfigFile("../testdata/a.yml")
dog.ReadConfig()
err := dog.WatchConfig(func() {
e := dog.Get("d.e")
log.Println("更新", e.Idx(e.Len()-1))
})
if err != nil {
panic(err)
}
log.Println(dog.Get("a").String())
go func() {
for {
e := dog.Get("d.e")
log.Println("获取", e.Idx(e.Len()-1))
}
}()
time.Sleep(time.Minute)
默认解析名称为字段名首字母小写,如果自定义请使用tag, doggie:"xxx"
//下面的会解析key为name,age的配置
type DefaultNameConfig struct {
Name string
Age int
}
//下面可以自定义, Name, Age
type CustomNameConfig struct {
Name string `doggie:"Name"`
Age int `doggie:"Age"`
}