package main
import (
"fmt"
"github.com/fsnotify/fsnotify"
"github.com/spf13/viper"
"log"
"os"
"path"
"time"
)
var Cfg EnvSD
type EnvSD struct {
Mysql Mysql `mapstructure:"mysql"`
Consul Consul `mapstructure:"consul"`
}
type Mysql struct {
Conn string `mapstructure:"conn"`
Desc string `mapstructure:"desc"`
Auth `mapstructure:",squash"` // viper 包匿名嵌套标识符为 squash
}
type Consul struct {
Addr string `mapstructure:"addr"`
Desc string `mapstructure:"desc"`
Auth `mapstructure:",squash"`
}
type Auth struct {
User string `mapstructure:"user"`
Password string `mapstructure:"password"`
}
func initConf() {
// 获取项目目录
exePath, _ := os.Executable()
projectPath := path.Dir(exePath)
viper.NewWithOptions(viper.KeyDelimiter("->")) // 修改 viper 的分隔符
viper.AddConfigPath(projectPath) // 配置文件路径
viper.SetConfigName("conf.yaml") // 配置文件名
viper.SetConfigType("yaml") // 配置文件类型
// 读取
if err := viper.ReadInConfig(); err != nil {
log.Fatalln("[pkg.class.func.read config failed] ", err.Error())
}
// 反序列化
viper.Unmarshal(&Cfg)
fmt.Printf("%+v\n", Cfg)
}
// watchFileUpdateConf 监听配置文件, 更新到Conf实例
func watchFileUpdateConf() {
viper.WatchConfig()
viper.OnConfigChange(func(e fsnotify.Event) {
// 更新可变的配置内容
viper.Unmarshal(&Cfg)
// 记录日志
log.Println(e.String())
log.Printf("%+v\n", Cfg)
})
}
func main() {
// 读取配置文件,解码到结构体
initConf()
// 监听文件变化
go watchFileUpdateConf()
// 模拟结构体发生改变时更新到文件, 将字段反序列化到结构体,存入文件
viper.Set("consul.addr", "9.9.9.9")
viper.UnmarshalKey("consul.addr", "9.9.9.9")
viper.WriteConfig()
// 模拟hang住
time.Sleep(60 * time.Second)
}
远程读取 consul kv 库
package main
import (
"fmt"
"github.com/spf13/viper"
_ "github.com/spf13/viper/remote"
)
func main() {
err := viper.AddRemoteProvider("consul", "http://service-epoch-cozzc:8500", "/test/server.json")
if err != nil {
fmt.Println(err.Error())
}
viper.SetConfigType("json") // Need to explicitly set this to json
err = viper.ReadRemoteConfig()
if err != nil {
fmt.Println(err.Error())
}
fmt.Println(viper.GetString("server.ip"))
fmt.Println(viper.GetString("server.port"))
}
watch机制
- 本地是用ionotify实现的
- 远程暂时只支持etcd, 使用轮询实现
参考链接
- http://www.manongjc.com/detail/54-fdqfrlykcewpwsq.html)