viper 11k Star 支持yaml,ini 支持 env ,命令行 等
最后更新于:2022-04-02 02:39:45
[TOC]
> [github](https://github.com/spf13/viper)
> [github 翻译的中文教程](https://mojotv.cn/2018/12/26/how-to-use-viper-configuration-in-golang)
## 概述
### 特点
* 设置默认值
* 从JSON,TOML,YAML,HCL,envfile和Java属性配置文件中读取
* 实时观看和重新读取配置文件(可选)
* 从环境变量中读取
* 从远程配置系统(etcd或Consul)中读取,并观察更改
* 从命令行标志读取
* 从缓冲区读取
* 设置显式值
**优先级**
* explicit call to`Set`
* flag
* env
* config
* key/value store
* default
## 安装
`go get github.com/spf13/viper`
## 教程
统一使用的配置信息
### 访问 yaml or json json 处理与 yaml 类似
### 配置信息转为结构体
### 使用 flag
运行 ``` > go run main.go --port 9000 hostAddress :127.0.0.1 , port:9000 ``` ### 监听配置信息 添加更新信息后,配置自动更改
### 使用环境变量
### 获取远程配置 [参考教程](https://learnku.com/articles/33908#fca496)
### 写入配置文件 ``` viper.WriteConfig() // writes current config to predefined path set by 'viper.AddConfigPath()' and 'viper.SetConfigName' viper.SafeWriteConfig() viper.WriteConfigAs("/path/to/my/.config") viper.SafeWriteConfigAs("/path/to/my/.config") // will error since it has already been written viper.SafeWriteConfigAs("/path/to/my/.other_config") ``` ## 查看多个配置地址 ``` v := viper.New() v.SetConfigName("app.conf") v.SetConfigType("ini") v.AddConfigPath("D:/go/antbiz/conf_dev") v.AddConfigPath("./conf/") err := v.ReadInConfig() ```
';
config/demo.yaml
``` TimeStamp: "2018-10-18 10:09:23" Address: "Shenzhen" Postcode: 518000 CompanyInfomation: Name: "Sunny" MarketCapitalization: 50000000 EmployeeNum: 200 Department: - "Finance" - "Design" - "Program" - "Sales" IsOpen: false ```### 访问 yaml or json json 处理与 yaml 类似
main.go
``` package main import ( "fmt" "github.com/spf13/viper" ) func main() { //读取yaml文件 v := viper.New() //设置读取的配置文件 v.SetConfigName("demo") //添加读取的配置文件路径 v.AddConfigPath("./config/") //设置配置文件类型,可不设置,自动识别 //v.SetConfigType("yaml") if err := v.ReadInConfig();err != nil { fmt.Printf("err:%s\n",err) } fmt.Print( v.GetInt("Postcode"), //518000 v.GetStringSlice("CompanyInfomation.Department")[0],//Finance ) } ```### 配置信息转为结构体
main.go
``` package main import ( "github.com/spf13/viper" "fmt" ) func main() { //读取yaml文件 v := viper.New() //设置读取的配置文件 v.SetConfigName("demo") //添加读取的配置文件路径 v.AddConfigPath("./config/") //设置配置文件类型,可不设置,自动识别 //v.SetConfigType("yaml") if err := v.ReadInConfig(); err != nil { panic( err) } //反序列化 yaml := parseYaml(v) fmt.Printf("%+v",yaml) /* result: {TimeStamp:2018-10-18 10:09:23 Address:Shenzhen Postcode:518000 CompanyInfomation:{Name:Sunny MarketCapitalization:50000000 EmployeeNum:200 Department:[Finance Design Program Sales] IsOpen:false}} */ } type CompanyInfomation struct { Name string MarketCapitalization int64 EmployeeNum int64 Department []interface{} IsOpen bool } type YamlSetting struct { TimeStamp string Address string Postcode int64 CompanyInfomation CompanyInfomation } func parseYaml(v *viper.Viper)(yamlObj YamlSetting ){ if err := v.Unmarshal(&yamlObj); err != nil { fmt.Printf("err:%s", err) } return yamlObj } ```### 使用 flag
main.go
``` ffunc main() { pflag.String("hostAddress", "127.0.0.1", "Server running address") pflag.Int64("port", 8080, "Server running port") pflag.Parse() //绑定 flag viper.BindPFlags(pflag.CommandLine) fmt.Printf("hostAddress :%s , port:%s", viper.GetString("hostAddress"), viper.GetString("port")) } ```运行 ``` > go run main.go --port 9000 hostAddress :127.0.0.1 , port:9000 ``` ### 监听配置信息 添加更新信息后,配置自动更改
main.go
``` package main import ( "fmt" "github.com/fsnotify/fsnotify" "github.com/spf13/viper" ) func main() { //读取yaml文件 v := viper.New() //设置读取的配置文件 v.SetConfigName("demo") //添加读取的配置文件路径 v.AddConfigPath("./config/") //设置配置文件类型 v.SetConfigType("yaml") if err := v.ReadInConfig(); err != nil { panic(err) } a1 := v.GetString("Address") fmt.Printf("%+v\n", a1) // Shenzhen // 设置监听回调函数(非必须) v.OnConfigChange(func(e fsnotify.Event) { a2 := v.GetString("Address")//Shenzhen1 值已更改 fmt.Printf("%+v\n", a2) fmt.Printf("%#v\n", e)//fsnotify.Event{Name:"/Users/idcpj/go/project/go-demo/viper/config/demo.yaml", Op:0x12} }) //开始监听 v.WatchConfig() } ```### 使用环境变量
main.gpo
``` package main import ( "fmt" "os" "github.com/spf13/viper" ) func main() { // 模拟环境变量 start prefix := "PROJECTNAME" envs := map[string]string{ "LOG_LEVEL": "INFO", "MODE": "DEV", "MYSQL_USERNAME": "root", "MYSQL_PASSWORD": "xxxx", } for k, v := range envs { os.Setenv(fmt.Sprintf("%s_%s", prefix, k), v) } // 模拟环境变量 end v := viper.New() v.SetEnvPrefix(prefix) v.AutomaticEnv() for k, _ := range envs { fmt.Printf("env `%s` = %s\n", k, v.GetString(k)) } } ```### 获取远程配置 [参考教程](https://learnku.com/articles/33908#fca496)
详情
``` package main import ( "fmt" "os" "github.com/spf13/viper" ) func main() { // 模拟环境变量 start prefix := "PROJECTNAME" envs := map[string]string{ "LOG_LEVEL": "INFO", "MODE": "DEV", "MYSQL_USERNAME": "root", "MYSQL_PASSWORD": "xxxx", } for k, v := range envs { os.Setenv(fmt.Sprintf("%s_%s", prefix, k), v) } // 模拟环境变量 end v := viper.New() v.SetEnvPrefix(prefix) v.AutomaticEnv() for k, _ := range envs { fmt.Printf("env `%s` = %s\n", k, v.GetString(k)) } } ```### 写入配置文件 ``` viper.WriteConfig() // writes current config to predefined path set by 'viper.AddConfigPath()' and 'viper.SetConfigName' viper.SafeWriteConfig() viper.WriteConfigAs("/path/to/my/.config") viper.SafeWriteConfigAs("/path/to/my/.config") // will error since it has already been written viper.SafeWriteConfigAs("/path/to/my/.other_config") ``` ## 查看多个配置地址 ``` v := viper.New() v.SetConfigName("app.conf") v.SetConfigType("ini") v.AddConfigPath("D:/go/antbiz/conf_dev") v.AddConfigPath("./conf/") err := v.ReadInConfig() ```