水的不行,就是翻译README,当时记的有点乱,刚好用到了又从笔记里翻出来看了一下,顺便发下

前言: 什么是Viper

Viper Github项目地址 : https://github.com/spf13/viper

Viper的描述是 Golang项目的完整配置文件解决方案,它几乎支持所有格式的配置文件。包括:

  • 默认配置
  • JSON, TOML, YAML, HCL, 环境变量文件和java的properties。
  • 监听和热加载配置文件 (可选)
  • 读取环境变量
  • 读取和监听远程的配置文件 ( etcd或者Consul )
  • 读取命令行传递参数
  • 从buffer中读取配置
  • 设置明确的配置值

Viper can be thought of as a registry for all of your applications configuration needs.

Viper的目标是让开发者可以专注于自身业务代码和功能代码的开发,viper来简易化处理关于配置的一切。

Viper可以找到加载和反序列化多种格式的配置文件,提供为不同的配置设置默认值以及覆写配置的机制,可以在不打破原有代码结构的情况下,采用别名系统来修改参数信息,等等

Viper加载配置值的优先级为:

磁盘上的配置文件>命令行标志位>环境变量>远程Key/Value存储>默认值

接下来,从两个部分来介绍Viper的使用

  • 第一部分,如何将配置文件读取到Viper实例
  • 第二部分,如何从Viper实例获取配置信息

如何将配置文件读取到Viper实例

1. 从本地文件读取
1
2
3
4
5
6
7
viper.SetConfigFile("./config.yaml")  //  指定配置文件名称

viper.SetConfigName("config")
viper.SetConfigType(".yaml")
viper.AddConfigPath("./") // 添加文件查找目录,可多次调用, 这三条合起来使用效果与第一条等同

err := viper.ReadInConfig() // 查找并读取找到的配置文件
2. 设置默认值
1
viper.SetDefault("name", "default")
3. 监听配置文件的变化

当配置文件在程序运行时被修改,viper可以监听到文件变化,从而实现热更新

1
2
3
4
viper.WatchConfig()
viper.OnConfigChange(func(e fsnotify.Event){
fmt.Println("config file changed: ", e.Name)
})
4. 从 io.Reader 读取配置
1
2
3
4
5
6
7
8
9
10
11
12
13
viper.SetConfigType("yaml")

yamlIoReader := []byte{
`
name: test,
age: 20,
pets:
- dog
- cat
`
}

viper.ReadConfig(bytes.NewBuffer(yamlIoReader))
5. 覆写

可以从环境变量,命令行或者运行逻辑获取值来覆写配置

1
viper.Set("name", "newName")
6. 注册使用别名系统
1
2
3
4
5
6
7
viper.RegisterAlias("loud", "Verbose")

viper.Set("verbose", true) // same result as next line
viper.Set("loud", true) // same result as prior line

viper.GetBool("loud") // true
viper.GetBool("verbose") // true
7. 环境变量
  • AutomaticEnv()

    自动预加载环境变量

  • BindEnv(string...) : error

    1
    2
    3
    接收一个参数时,该参数表示key值和变量名,比如 `GOPATH`, 

    两个参数时,第一个表示key,第二个表示变量名,比如 ("my_go_path", "GOAPTH"),可以通过`viper.Get("my_go_path")` 得到GOPATH值
  • SetEnvPrefix(string)

    1
    给环境变量加上前缀,会自动大写
  • SetEnvKeyReplacer(string...) *strings.Replacer

    1
    2
    使用strings.Replacer对象重写Env键到一定程度。如果要在Get()调用中使用或使用某些内容,
    但希望环境变量使用_分隔符,则此选项非常有用
  • AllowEmptyEnv(bool)

    1
    默认情况下,空环境变量被认为是未设置的,并将返回到下一个配置源。若要将空环境变量视为已设置的,请使用AllowEmptyEnv方法
8. 从远程 kv存储读取配置 (etcd / consul)

需要 import _ “github.com/spf13/viper/remote” 支持

// todo

从 viper获取值

基本从名字就可以看出使用场景了

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
func Get(key string) interface
func GetBool(key string) bool
func GetFloat64(key string) float64
func GetInt(key string) int
func GetIntSlice(key string) []int
func GetString(key string) string
func GetStringMap(key string) map[string]interface{}
func GetstringSlice(key string) []string
func GetStringMapString(key string) map[string]string

func GetTime(key string) time.Time
func GetDuration(key string) time.Duration

func IsSet(key string) bool

func AllSettings() map[string]interface{}

如果时嵌套的json结构,比如

1
2
3
4
5
6
7
8
9
{
"student1":{
"name": "jack",
"pets": [
"dog",
"cat",
]
}
}

使用

1
viper.GetString("student1.name")   //  jack, 通过 `.`访问嵌套
1
viper.GetString("student1.pets.0") // dog, 通过下标访问指定元素
提取子树
1
2
3
4
5
app:
one:
name: jack
two:
name: john

使用 one := viper.Sub(app.one)

反序列化

将viper中的配置信息反序列化到我们定义好的struct或者map等,有两种方法

1
2
3
func Unmarshal(rawVal interface{}) error

func UnmarshalKey(key string, rawVal interface{}) error