Viper
Viper是适用于Go应用程序的完整配置解决方案。它被设计用于在应用程序中工作,并且可以处理所有类型的配置需求和格式。
安装
go get -u github.com/spf13/viper1 介绍
Viper是适用于Go应用程序(包括Twelve-Factor App)的完整配置解决方案。它被设计用于在应用程序中工作,并且可以处理所有类型的配置需求和格式。它支持以下特性:
设置默认值
从
JSON、TOML、YAML、HCL、envfile和Java properties格式的配置文件读取配置信息实时监控和重新读取配置文件(可选)
从环境变量中读取
从远程配置系统(etcd或Consul)读取并监控配置变化
从命令行参数读取配置
从buffer读取配置
显式配置值
2 为什么选择Viper
Viper能够为你执行下列操作:
查找、加载和反序列化
JSON、TOML、YAML、HCL、INI、envfile和Java properties格式的配置文件。提供一种机制为你的不同配置选项设置默认值。
提供一种机制来通过命令行参数覆盖指定选项的值。
提供别名系统,以便在不破坏现有代码的情况下轻松重命名参数。
当用户提供了与默认值相同的命令行或配置文件时,可以很容易地分辨出它们之间的区别。
Viper会按照下面的优先级。每个项目的优先级都高于它下面的项目:
显示调用
Set设置值命令行参数(flag)
环境变量
配置文件
key/value存储
默认值 注意:Viper配置的key是大小写不敏感的
3 把值存入viper
3.1 设置默认值
一个好的配置系统应该支持默认值。键不需要默认值,但如果没有通过配置文件、环境变量、远程配置或命令行标志(flag)设置键,则默认值非常有用。
3.2 读取配置文件
Viper需要最少知道在哪里查找配置文件的配置。Viper支持JSON、TOML、YAML、HCL、envfile和Java properties格式的配置文件。Viper可以搜索多个路径,但目前单个Viper实例只支持单个配置文件。Viper不默认任何配置搜索路径,将默认决策留给应用程序。
同级目录下的同名文件,会按照支持顺序读取
在加载配置文件出错时,你可以像下面这样处理找不到配置文件的特定情况:
你也可以有不带扩展名的文件,并以编程方式指定其格式。对于位于用户$HOME目录中的配置文件没有任何扩展名,如.bashrc
3.3 合并配置文件
用途:与 ReadInConfig 类似,但合并配置内容到现有的配置存储中,而不是覆盖。
适用场景:需要从多个配置文件加载配置(例如 base.yaml + override.yaml)。
3.4 读取环境变量
3.4.1 启用环境变量自动绑定
使用 AutomaticEnv() 让 Viper 自动绑定所有环境变量到配置键,键名默认转换为大写+下划线格式:
3.4.2 设置环境变量前缀
通过 SetEnvPrefix 设置前缀,避免与其他应用的环境变量冲突:
3.4.3 手动绑定指定环境变量
使用 BindEnv 将特定环境变量绑定到配置键(支持多个备选环境变量名):
3.4.4 读取嵌套配置的环境变量
Viper 支持用 . 分隔的嵌套键名,对应环境变量需转换为 大写+下划线 格式:
4 写入配置文件
WriteConfig - 将当前的
viper配置写入预定义的路径并覆盖(如果存在的话)。如果没有预定义的路径,则报错。SafeWriteConfig - 将当前的
viper配置写入预定义的路径。如果没有预定义的路径,则报错。如果存在,将不会覆盖当前的配置文件。WriteConfigAs - 将当前的
viper配置写入给定的文件路径。将覆盖给定的文件(如果它存在的话)。SafeWriteConfigAs - 将当前的
viper配置写入给定的文件路径。不会覆盖给定的文件(如果它存在的话)。
根据经验,标记为safe的所有方法都不会覆盖任何文件,而是直接创建(如果不存在),而默认行为是创建或截断。
4.1 监控并重新读取文件
Viper支持在运行时实时读取配置文件的功能。
只需告诉viper实例watchConfig。可选地,你可以为Viper提供一个回调函数,以便在每次发生更改时运行。
4.2 从io.Reader读取配置
Viper预先定义了许多配置源,如文件、环境变量、标志和远程K/V存储,但你不受其约束。你还可以实现自己所需的配置源并将其提供给viper。
4.3 覆盖设置
4.4 别名设置
5 获取值
在Viper中,有几种方法可以根据值的类型获取值。存在以下功能和方法:
Get(key string) : interface{}GetBool(key string) : boolGetFloat64(key string) : float64GetInt(key string) : intGetIntSlice(key string) : []intGetString(key string) : stringGetStringMap(key string) : map[string]interface{}GetStringMapString(key string) : map[string]stringGetStringSlice(key string) : []stringGetTime(key string) : time.TimeGetDuration(key string) : time.DurationIsSet(key string) : boolAllSettings() : map[string]interface{}
需要认识到的一件重要事情是,每一个Get方法在找不到值的时候都会返回零值。为了检查给定的键是否存在,提供了IsSet()方法。
5.1 访问嵌套的键
访问器方法也接受深度嵌套键的格式化路径。例如,如果加载下面的JSON文件:
Viper可以通过传入.分隔的路径来访问嵌套字段:
5.2 反序列化
你还可以选择将所有或特定的值解析到结构体、map等。
有两种方法可以做到这一点:
Unmarshal(rawVal interface{}) : errorUnmarshalKey(key string, rawVal interface{}) : error
举个例子:
如果你想要解析那些键本身就包含.(默认的键分隔符)的配置,你需要修改分隔符:
6 使用多个viper实例
你还可以在应用程序中创建许多不同的viper实例。每个都有自己独特的一组配置和值。每个人都可以从不同的配置文件,key value存储区等读取数据。每个都可以从不同的配置文件、键值存储等中读取。viper包支持的所有功能都被镜像为viper实例的方法。
例如:
当使用多个viper实例时,由用户来管理不同的viper实例。
7 远程配置中心读取
7.1 ReadRemoteConfig() error
ReadRemoteConfig() error用途:从远程配置中心(如 etcd、Consul、AWS Parameter Store 等)加载配置。 依赖:需要先配置远程访问的地址和认证信息。
7.2 WatchRemoteConfig() error
WatchRemoteConfig() error用途:启动后台监控,当远程配置发生变化时自动重新加载。
最后更新于