介绍
Viper适用于Go应用程序的完整配置解决方案,并且能处理所有类型的配置需求和格式。
- 设置默认值
- 读取JSON,TOML,YAML,HCL,enfile和java properties格式的配置文件读取配置信息
- 实时监控和读取配置文件(可选)
- 从环境变量中读取
- 从远程配置系统(etcd/consul)读取并监控配置变化
- 从命令行参数读取配置
- 从buffer读取配置
- 显示配置值
安装
go get github.com/spf13/viper
基本使用
设置默认值
viper.SetDefault("ContentDir", "content")
viper.SetDefault("LayoutDir", "layouts")
viper.SetDefault("Taxonomies", map[string]string{"tag": "tags", "category": "categories"})
读取配置文件
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))
}
写入配置文件
- WriteConfig - 将当前的
viper配置写入预定义的路径并覆盖(如果存在的话)。如果没有预定义的路径,则报错。 - SafeWriteConfig - 将当前的
viper配置写入预定义的路径。如果没有预定义的路径,则报错。如果存在,将不会覆盖当前的配置文件。 - WriteConfigAs - 将当前的
viper配置写入给定的文件路径。将覆盖给定的文件(如果它存在的话)。 - SafeWriteConfigAs - 将当前的
viper配置写入给定的文件路径。不会覆盖给定的文件(如果它存在的话)。
viper.WriteConfig() // 将当前配置写入“viper.AddConfigPath()”和“viper.SetConfigName”设置的预定义路径
viper.SafeWriteConfig()
viper.WriteConfigAs("/path/to/my/.config")
viper.SafeWriteConfigAs("/path/to/my/.config") // 因为该配置文件写入过,所以会报错
viper.SafeWriteConfigAs("/path/to/my/.other_config")
监控并重新读取配置文件
Viper支持在运行时实时读取配置文件的功能。
需要重新启动服务器以使配置生效的日子已经一去不复返了,viper驱动的应用程序可以在运行时读取配置文件的更新,而不会错过任何消息。
只需告诉viper实例watchConfig。可选地,你可以为Viper提供一个回调函数,以便在每次发生更改时运行。
确保在调用WatchConfig()之前添加了所有的配置路径。
viper.WatchConfig()
viper.OnConfigChange(func(e fsnotify.Event) {
// 配置文件发生变更之后会调用的回调函数
fmt.Println("Config file changed:", e.Name)
}
从consul或etcd中读取
etcd
viper.AddRemoteProvider("etcd", "http://127.0.0.1:4001","/config/hugo.json")
viper.SetConfigType("json") // 因为在字节流中没有文件扩展名,所以这里需要设置下类型。支持的扩展名有 "json", "toml", "yaml", "yml", "properties", "props", "prop", "env", "dotenv"
err := viper.ReadRemoteConfig()
consul
你需要 Consul Key/Value存储中设置一个Key保存包含所需配置的JSON值。例如,创建一个keyMY_CONSUL_KEY将下面的值存入Consul key/value 存储:
{
"port": 8080,
"hostname": "liwenzhou.com"
}
viper.AddRemoteProvider("consul", "localhost:8500", "MY_CONSUL_KEY")
viper.SetConfigType("json") // 需要显示设置成json
err := viper.ReadRemoteConfig()
fmt.Println(viper.Get("port")) // 8080
fmt.Println(viper.Get("hostname")) // liwenzhou.com
go简单集成
func Viper(path ...string) *viper.Viper {
var config string
//读取配置优先级,先读取命令行>环境变量>默认值
if len(path) == 0 {
flag.StringVar(&config, "c", "", "choose congif file")
flag.Parse()
if config == "" {
if configEnv := os.Getenv(utils.ConfigEnv); configEnv == "" {
config = utils.ConfigFile
fmt.Printf("正在使用默認值%s",config)
}else{
config=configEnv
fmt.Printf("正在使用环境变量%s",configEnv)
}
}
}else{
config=path[0]
fmt.Printf("使用传入的配置文件%s",config)
}
v:=viper.New()
v.SetConfigFile(config)
v.SetConfigType("yaml")
err:=v.ReadInConfig()
if err!=nil{
panic(fmt.Errorf("fatal error config file %s",err).(any))
}
//实时监听配置的变更
v.WatchConfig()
//配置变更回调函数
v.OnConfigChange(func(e fsnotify.Event) {
fmt.Println("config file changed",e.Name)
fmt.Println("config file changed",global.GVA_CONFIG.Redis)
if err:=v.Unmarshal(&global.GVA_CONFIG);err!=nil{
fmt.Println(err)
}
})
//上面只有配置变更才会执行,所以需要初始化映射配置
if err := v.Unmarshal(&global.GVA_CONFIG); err != nil {
fmt.Println(err)
}
return v
}