Go Viper - 初探

什么是Viper?

Viper是配置文件的解决方案。支持:

  • 设置默认配置。
  • 从 JSON,TOML,YAML,HCL,Java properties 的文件中读取配置。
  • 实时重新读取配置文件。
  • 从远程读取配置,可观察到配置文件的改变。
  • 从命令行参数读取配置(command line flags)
  • 从缓存中读取配置
  • 设置明确值的配置

Viper读取配置优先级

  • Set明确设置的配置
  • io.Reader读取配置
  • 命令行参数
  • 环境变量
  • 配置文件
  • key/value存储
  • 默认配置

Viper使用示例

Set明确设置的配置

// 优先级最高,覆盖其他来源的denyu配置
viper.Set("denyu", "陈宇")

io.Reader中读取配置

viper.SetConfigType("yaml")
var yamlExample = []byte(`
name: denyu
hobbies:
- go
- java
clothing:
jacket: leather
`)

viper.ReadConfig(bytes.NewBuffer(yamlExample))

viper.Get("name") // this would be "denyu"

命令行读取配置

pflag.Int("flagname", 1234, "help message for flagname")

pflag.Parse()
viper.BindPFlags(pflag.CommandLine)

i := viper.GetInt("flagname")
// 一般程序用的都是内置flag
import (
"flag"
"github.com/spf13/pflag"
...
)

func main() {
flag.Int("flagname", 1234, "help message for flagname")

pflag.CommandLine.AddGoFlagSet(flag.CommandLine)
pflag.Parse()
viper.BindPFlags(pflag.CommandLine)

i := viper.GetInt("flagname")
...
}

环境变量中读取配置

// case 1
// 这里环境变量的名字必须大写
viper.SetEnvPrefix("sss")
BindEnv("id")
os.Setenv("SSS_ID", "0001")
id := Get("id") // 0001

// case 2
// 如果BindEnv传第二个参数则不加前缀
// 环境变量名不一定大写
viper.SetEnvPrefix("sss")
BindEnv("id", "sSs_Id")
os.Setenv("sSs_Id", "0001")
id := Get("id") // 0001

// case 3
os.Setenv("SSS_ID", "0001")
viper.AutomaticEnv()
id := viper.Get("sss_id") // 0001

// case 4
SetEnvPrefix("sss")
os.Setenv("SSS_ID", "0001")
viper.AutomaticEnv()
id := viper.Get("id") // 0001

配置文件中读取配置

viper.SetConfigName("config")
viper.AddConfigPath(".")
err := viper.ReadInConfig()
if err != nil {
panic(err)
}

远程key/value读取配置

{
"port": 8080
}

viper.AddRemoteProvider("consul", "localhost:8500", "MY_CONSUL_KEY")
viper.SetConfigType("json")
err := viper.ReadRemoteConfig()

fmt.Println(viper.Get("port")) // 8080

默认配置

viper.SetDefault("denyu", "陈宇")

实时重新读取配置文件

package main

import (
"fmt"
"sync"

"github.com/spf13/viper"
"github.com/fsnotify/fsnotify"
)

func main() {
var waitGroup sync.WaitGroup
waitGroup.Add(1)

viper.SetConfigName("config")
viper.AddConfigPath(".")
err := viper.ReadInConfig()
if err != nil {
panic(fmt.Errorf("Fatal error config file: %s \n", err))
}

// 实时重新读取配置文件
viper.WatchConfig()
// 如果文件配置文件发生改变就会触发
viper.OnConfigChange(func(e fsnotify.Event) {
fmt.Println("Config file changed:", e.Name)
fmt.Println(viper.Get("denyu"))
})

fmt.Println(viper.Get("denyu"))

waitGroup.Wait()
}

// 控制台打印数据如下
// 陈宇
// 当改变config.json文件时控制台打印如下
// Config file changed: /Users/mike/go/src/github.com/demo/config.json
// 陈宇1

使用别名

viper.RegisterAlias("dy", "mk")

viper.Set("dy", "denyu")
viper.Set("mk", "mike")

viper.Get("dy") // denyu
viper.Get("mk") // mike