介绍
viper [15K] 是一个可以读远程、本地(JSON, TOML, YAML, HCL 等) 配置文件的工具。同时支持监听文件变动(fsnotify)和转换成结构体功能。
使用
- 巧用 viper 实现多环境配置
- 读取到结构体
- go-gugu
- toml-to-go - 可以根据toml文件来生成go结构体
监听文件变动
以往我们修改配置文件要么重启服务,要么搞一个api去修改,Viper利用fsnotify把这个功能帮我们实现了。只要配置文件被修改保存后,我们事先注册的watch函数就回被触发,只要我们在这里面添加更新操作就ok了。
但是有很多配置是在程序初始化时加载的,此后服务已开启,即使重新修改了配置文件,触发了watch回调,也不会对服务中的配置进行更新,所以这个功能针对于即用即取的配置更好用,服务型配置需要额外代码支持。
示例
package viperine_test
import (
"fmt"
"github.com/fsnotify/fsnotify"
"github.com/lifegit/go-gulu/viperine"
"github.com/sirupsen/logrus"
"github.com/spf13/viper"
"testing"
)
type GlobalConf struct {
Server struct {
Addr string `toml:"addr"`
} `toml:"server"`
}
var Global GlobalConf
func TestName(t *testing.T) {
v, err := LocalConfToViper([]string{"./conf/base.toml"}, &Global, func(event fsnotify.Event, viper *viper.Viper) {
if event.Op != fsnotify.Remove {
_ = viper.Unmarshal(&Global)
}
})
if err != nil {
logrus.WithError(err).Fatal(err)
}
fmt.Println(Global, v)
}
func LocalConfToViper(pathNames []string, callData interface{}, watchChange func(event fsnotify.Event, viper *viper.Viper)) (v *viper.Viper, err error) {
v = viper.New()
for _, value := range pathNames {
v.SetConfigFile(value)
if err = v.MergeInConfig(); err != nil {
return
}
if watchChange != nil {
v.WatchConfig()
v.OnConfigChange(func(in fsnotify.Event) {
v.SetConfigFile(in.Name)
if err = v.MergeInConfig(); err == nil {
watchChange(in, v)
}
})
}
}
err = v.Unmarshal(&callData)
return
}