企业🤖AI智能体构建引擎,智能编排和调试,一键部署,支持私有化部署方案 广告
[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` ## 教程 统一使用的配置信息 <details> <summary>config/demo.yaml</summary> ``` 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 ``` </details> <br /> ### 访问 yaml or json json 处理与 yaml 类似 <details> <summary>main.go</summary> ``` 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 ) } ``` </details> <br /> ### 配置信息转为结构体 <details> <summary>main.go</summary> ``` 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 } ``` </details> <br /> ### 使用 flag <details> <summary>main.go</summary> ``` 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")) } ``` </details> <br/> 运行 ``` > go run main.go --port 9000 hostAddress :127.0.0.1 , port:9000 ``` ### 监听配置信息 添加更新信息后,配置自动更改 <details> <summary> main.go</summary> ``` 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() } ``` </details> <br /> ### 使用环境变量 <details> <summary>main.gpo</summary> ``` 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)) } } ``` </details> <br /> ### 获取远程配置 [参考教程](https://learnku.com/articles/33908#fca496) <details> <summary>详情</summary> ``` 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)) } } ``` </details> <br /> ### 写入配置文件 ``` 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() ```