Viper
viper
我们将使用 Viper 包来作为yaml 和 config 信息的基础库。
Viper 是 Go 生态圈里一个很知名的项目,在 GitHub 上有接近 1.8 万个 star。
它支持以下特性:
- 设置默认值(存入时设置)
- 支持格式配置信息的格式包括
JSON
、TOML
、YAML
、HCL
、envfile
和Java properties
- 实时监控和重新读取配置文件(可选)
- 从环境变量中读取
- 从远程配置系统(etcd 或 Consul)读取并监控配置变化
- 从命令行参数读取配置
- 从 buffer 读取配置
- 显式配置值
Viper 的功能比较丰富,这意味着面对多变的需求时我们可以很灵活。且作为明星项目,严格测试、使用广泛,很适合作为我们的配置模块的底层包。
安装
1 |
|
viper基本用法
config.json
1 |
|
config.yaml
1 |
|
建立默认值
一个好的配置系统应该支持默认值。键不需要默认值,但如果没有通过配置文件、环境变量、远程配置或命令行标志(flag)设置键,则默认值非常有用。
例如:
1 |
|
读取配置文件
Viper需要最少知道在哪里查找配置文件的配置。Viper支持JSON
、TOML
、YAML
、HCL
、envfile
和Java properties
格式的配置文件。Viper可以搜索多个路径,但目前单个Viper实例只支持单个配置文件。Viper不默认任何配置搜索路径,将默认决策留给应用程序。
下面是一个如何使用Viper搜索和读取配置文件的示例。不需要任何特定的路径,但是至少应该提供一个配置文件预期出现的路径。
1 |
|
在加载配置文件出错时,你可以像下面这样处理找不到配置文件的特定情况:
1 |
|
注意[自1.6起]: 你也可以有不带扩展名的文件,并以编程方式指定其格式。对于位于用户$HOME
目录中的配置文件没有任何扩展名,如.bashrc
。
这里补充两个问题供读者解答并自行验证
当你使用如下方式读取配置时,viper会从./conf
目录下查找任何以config
为文件名的配置文件,如果同时存在./conf/config.json
和./conf/config.yaml
两个配置文件的话,viper
会从哪个配置文件加载配置呢?
1 |
|
在上面两个语句下搭配使用viper.SetConfigType("yaml")
指定配置文件类型可以实现预期的效果吗?
使用环境变量
Viper完全支持环境变量。这使Twelve-Factor App
开箱即用。有五种方法可以帮助与ENV协作:
AutomaticEnv()
BindEnv(string...) : error
SetEnvPrefix(string)
SetEnvKeyReplacer(string...) *strings.Replacer
AllowEmptyEnv(bool)
使用ENV变量时,务必要意识到Viper将ENV变量视为区分大小写。
Viper提供了一种机制来确保ENV变量是惟一的。通过使用SetEnvPrefix
,你可以告诉Viper在读取环境变量时使用前缀。BindEnv
和AutomaticEnv
都将使用这个前缀。
BindEnv
使用一个或两个参数。第一个参数是键名称,第二个是环境变量的名称。环境变量的名称区分大小写。如果没有提供ENV变量名,那么Viper将自动假设ENV变量与以下格式匹配:前缀+ “_” +键名全部大写。当你显式提供ENV变量名(第二个参数)时,它 不会 自动添加前缀。例如,如果第二个参数是“id”,Viper将查找环境变量“ID”。
在使用ENV变量时,需要注意的一件重要事情是,每次访问该值时都将读取它。Viper在调用BindEnv
时不固定该值。
AutomaticEnv
是一个强大的助手,尤其是与SetEnvPrefix
结合使用时。调用时,Viper会在发出viper.Get
请求时随时检查环境变量。它将应用以下规则。它将检查环境变量的名称是否与键匹配(如果设置了EnvPrefix
)。
SetEnvKeyReplacer
允许你使用strings.Replacer
对象在一定程度上重写 Env 键。如果你希望在Get()
调用中使用-
或者其他什么符号,但是环境变量里使用_
分隔符,那么这个功能是非常有用的。可以在viper_test.go
中找到它的使用示例。
或者,你可以使用带有NewWithOptions
工厂函数的EnvKeyReplacer
。与SetEnvKeyReplacer
不同,它接受StringReplacer
接口,允许你编写自定义字符串替换逻辑。
默认情况下,空环境变量被认为是未设置的,并将返回到下一个配置源。若要将空环境变量视为已设置,请使用AllowEmptyEnv
方法。
Env 示例:
1 |
|
从Viper获取值
在Viper中,有几种方法可以根据值的类型获取值。存在以下功能和方法:
Get(key string) : interface{}
GetBool(key string) : bool
GetFloat64(key string) : float64
GetInt(key string) : int
GetIntSlice(key string) : []int
GetString(key string) : string
GetStringMap(key string) : map[string]interface{}
GetStringMapString(key string) : map[string]string
GetStringSlice(key string) : []string
GetTime(key string) : time.Time
GetDuration(key string) : time.Duration
IsSet(key string) : bool
AllSettings() : map[string]interface{}
需要认识到的一件重要事情是,每一个Get方法在找不到值的时候都会返回零值。为了检查给定的键是否存在,提供了IsSet()
方法。
例如:
1 |
|