介绍
是适用于Go应用程序的完整配置解决方案。它被设计用于在应用程序中工作,并且可以处理所有类型的配置需求和格式它支持以下特性:他就是一个配置管理的三方库
<li>
设置默认值
</li><li>
从JSON
、TOML
、YAML
、HCL
、envfile
和Java properties
格式的配置文件读取配置信息
</li><li>
实时监控和重新读取配置文件(可选)
</li><li>
从环境变量中读取
</li><li>
从远程配置系统(etcd或Consul)读取并监控配置变化
</li><li>
从命令行参数读取配置
</li><li>
从buffer读取配置
</li><li>
显式配置值
</li>
为什么选择Viper?
viper相当于一个万能机器,用viper可以操作几乎所有的配置文件
Viper能够为你执行下列操作:
<li>
查找、加载和反序列化JSON
、TOML
、YAML
、HCL
、INI
、envfile
和Java properties
格式的配置文件。
</li><li>
提供一种机制为你的不同配置选项设置默认值。
</li><li>
提供一种机制来通过命令行参数覆盖指定选项的值。
</li><li>
提供别名系统,以便在不破坏现有代码的情况下轻松重命名参数。
</li><li>
当用户提供了与默认值相同的命令行或配置文件时,可以很容易地分辨出它们之间的区别。
</li>
Viper会按照下面的优先级。从高到低:
<li>
显示调用Set
设置值
</li><li>
命令行参数(flag)
</li><li>
环境变量
</li><li>
配置文件
</li><li>
key/value存储
</li><li>
默认值
</li>
重要: 目前Viper配置的键(Key)是大小写不敏感的。目前正在讨论是否将这一选项设为可选。
怎么存值?
默认值
作用:在读取配置文件前,先设置默认的配置项,如果读取配置文件后,没有找到配置项,那么就默认值就显得尤为重要
读取配置文件
viper读取文件前,搜索文件的特点:
<li>
支持JSON
、TOML
、YAML
、HCL
、envfile
和Java properties
格式的配置文件
</li><li>
viper可以搜索多个路径(设置了多个可能路径),单个viper加载一个配置文件(一致性、防止产生冲突)
</li><li>
Viper不默认任何配置搜索路径,将默认决策留给应用程序。(随机搜索)
</li>
注意:随机搜索,但是需要提前提供至少一个路径
eg:
<pre>
viper.SetConfigFile("./config.yaml") // 指定配置文件路径
//viper.SetConfigName("config") // 配置文件名称(无扩展名)
//viper.SetConfigType("yaml") // 如果配置文件的名称中没有扩展名,则需要配置此项
//这里可以直接指定该文件名和文件路径
//也可以只提供名字和后缀
viper.AddConfigPath("/etc/appname/") // 查找配置文件所在的路径
viper.AddConfigPath("$HOME/.appname") // 多次调用以添加多个搜索路径
viper.AddConfigPath(".") // 还可以在工作目录中查找配置
err := viper.ReadInConfig() // 查找并读取配置文件
if err != nil { // 处理读取配置文件的错误
panic(fmt.Errorf("Fatal error config file: %s \n", err))
}
</pre>
在加载配置文件出错时,你可以像下面这样处理找不到配置文件的特定情况:
<pre>
//ReadInConfig() 读取并解析配置文件
if err := viper.ReadInConfig(); err != nil {
if _, ok := err.(viper.ConfigFileNotFoundError); ok {
// 配置文件未找到错误;如果需要可以忽略
} else {
// 配置文件被找到,但产生了另外的错误
}
}
// 配置文件找到并成功解析</pre>
追问:
当你使用如下方式读取配置时,viper会从./conf
目录下查找任何以config
为文件名的配置文件,如果同时存在./conf/config.json
和./conf/config.yaml
两个配置文件的话,viper
会从哪个配置文件加载配置呢?
<pre>
viper.SetConfigName("config")
viper.AddConfigPath("./conf")</pre>
在上面两个语句下搭配使用viper.SetConfigType("yaml")
指定配置文件类型可以实现预期的效果吗?
<pre>
答:由于Viper 会优先加载符合其默认配置文件类型优先级顺序的文件。Viper 默认的配置文件类型优先级顺序为:JSON、TOML、YAML、HCL、envfile、Java properties。
1.会从./config.json加载配置(原因是viper有默认的加载顺序)
2.指定了文件类型,可以达到预期效果,从./config.yaml加载</pre>
*合并其他配置源
监控并重新读取配置文件
viper支持热加载(实施地读取配置文件)
viper只需要调用WatchConfig(),就可以做到监控读取配置文件的功能
注意:确保在调用WatchConfig()
之前添加了所有的配置路径。
另外,如果在配置发生实时变动时,想要做一些动作,可以为Viper提供一个回调函数,以便在每次发生更改时运行。
<pre>
//eg: 调用 OnConfigChange( 回调函数 )
viper.OnConfigChange(func(e fsnotify.Event) {
// 配置文件发生变更之后会调用的回调函数
fmt.Println("Config file changed:", e.Name)
})</pre>
从viper获取值
在Viper中,有几种方法可以根据值的类型获取值。存在以下功能和方法:
<li>
Get(key string) : interface{}
</li><li>
GetBool(key string) : bool
</li><li>
GetFloat64(key string) : float64
</li><li>
GetInt(key string) : int
</li><li>
GetIntSlice(key string) : []int
</li><li>
GetString(key string) : string
</li><li>
GetStringMap(key string) : map[string]interface{}
</li><li>
GetStringMapString(key string) : map[string]string
</li><li>
GetStringSlice(key string) : []string
</li><li>
GetTime(key string) : time.Time
</li><li>
GetDuration(key string) : time.Duration
</li><li>
IsSet(key string) : bool
</li><li>
AllSettings() : map[string]interface{}
</li>
需要认识到的一件重要事情是,每一个Get方法在找不到值的时候都会返回零值。为了检查给定的键是否存在,提供了IsSet()
方法。
例如:
<pre>
viper.GetString("logfile") // 不区分大小写的设置和获取
if viper.GetBool("verbose") {
fmt.Println("verbose enabled")
}</pre>
了解了主要的工作步骤,下面是一些关于viper的提供的便利: