介绍

viper [15K] 是一个可以读远程、本地(JSON, TOML, YAML, HCL 等) 配置文件的工具。同时支持监听文件变动(fsnotify)和转换成结构体功能。

使用

  1. 巧用 viper 实现多环境配置
  2. 读取到结构体
  3. go-gugu
  4. toml-to-go - 可以根据toml文件来生成go结构体

监听文件变动

以往我们修改配置文件要么重启服务,要么搞一个api去修改,Viper利用fsnotify把这个功能帮我们实现了。只要配置文件被修改保存后,我们事先注册的watch函数就回被触发,只要我们在这里面添加更新操作就ok了。

但是有很多配置是在程序初始化时加载的,此后服务已开启,即使重新修改了配置文件,触发了watch回调,也不会对服务中的配置进行更新,所以这个功能针对于即用即取的配置更好用,服务型配置需要额外代码支持。

示例

  1. package viperine_test
  2. import (
  3. "fmt"
  4. "github.com/fsnotify/fsnotify"
  5. "github.com/lifegit/go-gulu/viperine"
  6. "github.com/sirupsen/logrus"
  7. "github.com/spf13/viper"
  8. "testing"
  9. )
  10. type GlobalConf struct {
  11. Server struct {
  12. Addr string `toml:"addr"`
  13. } `toml:"server"`
  14. }
  15. var Global GlobalConf
  16. func TestName(t *testing.T) {
  17. v, err := LocalConfToViper([]string{"./conf/base.toml"}, &Global, func(event fsnotify.Event, viper *viper.Viper) {
  18. if event.Op != fsnotify.Remove {
  19. _ = viper.Unmarshal(&Global)
  20. }
  21. })
  22. if err != nil {
  23. logrus.WithError(err).Fatal(err)
  24. }
  25. fmt.Println(Global, v)
  26. }
  27. func LocalConfToViper(pathNames []string, callData interface{}, watchChange func(event fsnotify.Event, viper *viper.Viper)) (v *viper.Viper, err error) {
  28. v = viper.New()
  29. for _, value := range pathNames {
  30. v.SetConfigFile(value)
  31. if err = v.MergeInConfig(); err != nil {
  32. return
  33. }
  34. if watchChange != nil {
  35. v.WatchConfig()
  36. v.OnConfigChange(func(in fsnotify.Event) {
  37. v.SetConfigFile(in.Name)
  38. if err = v.MergeInConfig(); err == nil {
  39. watchChange(in, v)
  40. }
  41. })
  42. }
  43. }
  44. err = v.Unmarshal(&callData)
  45. return
  46. }