Go一站式配置管理工具Viper的使用教程
什么是Viper
Viper是一個方便Go語言應用程序處理配置信息的庫。它可以處理多種格式的配置。它支持的特性:
- 設置默認值
- 從JSON、TOML、YAML、HCL和Java properties文件中讀取配置數(shù)據(jù)
- 可以監(jiān)視配置文件的變動、重新讀取配置文件
- 從環(huán)境變量中讀取配置數(shù)據(jù)
- 從遠端配置系統(tǒng)中讀取數(shù)據(jù),并監(jiān)視它們(比如etcd、Consul)
- 從命令參數(shù)中讀物配置
- 從buffer中讀取
- 調用函數(shù)設置配置信息
為什么要使用Viper
在構建現(xiàn)代應用程序時,您不必擔心配置文件格式; 你可以專注于構建出色的軟件。
Viper 可以做如下工作:
- 加載并解析JSON、TOML、YAML、HCL 或 Java properties 格式的配置文件
- 可以為各種配置項設置默認值
- 可以在命令行中指定配置項來覆蓋配置值
- 提供了別名系統(tǒng),可以不破壞現(xiàn)有代碼來實現(xiàn)參數(shù)重命名
- 可以很容易地分辨出用戶提供的命令行參數(shù)或配置文件與默認相同的區(qū)別
Viper讀取配置信息的優(yōu)先級順序,從高到低,如下:
- 顯式調用Set函數(shù)
- 命令行參數(shù)
- 環(huán)境變量
- 配置文件
- key/value 存儲系統(tǒng)
- 默認值
Viper 的配置項的key不區(qū)分大小寫。
項目地址:https://github.com/spf13/viper
使用
設置默認值
默認值不是必須的,如果配置文件、環(huán)境變量、遠程配置系統(tǒng)、命令行參數(shù)、Set函數(shù)都沒有指定時,默認值將起作用。
viper.SetDefault("name", "xiaoming") viper.SetDefault("age", "12") viper.SetDefault("notifyList", []string{"xiaohong","xiaoli","xiaowang"})
讀取配置文件
Viper支持JSON、TOML、YAML、HCL和Java properties文件。
Viper可以搜索多個路徑,但目前單個Viper實例僅支持單個配置文件。
Viper默認不搜索任何路徑。
以下是如何使用Viper搜索和讀取配置文件的示例。
路徑不是必需的,但最好至少應提供一個路徑,以便找到一個配置文件。
viper.SetConfigName("dbConfig") // 設置配置文件名 (不帶后綴) viper.AddConfigPath("/workspace/appName/") // 第一個搜索路徑 viper.AddConfigPath("/workspace/appName1") // 可以多次調用添加路徑 viper.AddConfigPath(".") // 比如添加當前目錄 err := viper.ReadInConfig() // 搜索路徑,并讀取配置數(shù)據(jù) if err != nil { panic(fmt.Errorf("Fatal error config file: %s \n", err)) }
監(jiān)視配置文件,重新讀取配置數(shù)據(jù)
Viper支持讓你的應用程序在運行時擁有讀取配置文件的能力。
只需要調用viper實例的WatchConfig函數(shù),你也可以指定一個回調函數(shù)來獲得變動的通知。
viper.WatchConfig() viper.OnConfigChange(func(e fsnotify.Event) { fmt.Println("Config file changed:", e.Name) })
從 io.Reader 中讀取配置
Viper預先定義了許多配置源,例如文件、環(huán)境變量、命令行參數(shù)和遠程K / V存儲系統(tǒng)。也可以實現(xiàn)自己的配置源,并提供給viper。
現(xiàn)在有如下yaml文件:
userName: "xiaoming" address: "廣州市XXX" sex: 1 company: name: "xxx" employeeId: 1000 department: - "技術部"
讀取文件的代碼如下:
package main import ( "fmt" "github.com/spf13/viper" ) type UserInfo struct { UserName string Address string Sex byte Company Company } type Company struct { Name string EmployeeId int Department []interface{} } func main() { //讀取yaml文件 v := viper.New() //設置讀取的配置文件名 v.SetConfigName("userInfo") //windows環(huán)境下為%GOPATH,linux環(huán)境下為$GOPATH v.AddConfigPath("/Users/yangyue/workspace/go/src/webDemo/") //設置配置文件類型 v.SetConfigType("yaml") if err := v.ReadInConfig();err != nil { fmt.Printf("err:%s\n",err) } fmt.Printf("userName:%s sex:%s company.name:%s \n", v.Get("userName"), v.Get("sex"), v.Get("company.name")) //也可以直接反序列化為Struct var userInfo UserInfo if err := v.Unmarshal(&userInfo) ; err != nil{ fmt.Printf("err:%s",err) } fmt.Println(userInfo) }
上面的代碼使用兩種方式獲取配置文件:第一種直接解析為key,value;第二種你可以手動的反序列化為Struct。
從命令行參數(shù)中讀取
package main import ( "fmt" "github.com/spf13/pflag" "github.com/spf13/viper" ) func main() { pflag.String("ip", "127.0.0.1", "Server running address") pflag.Int64("port", 8080, "Server running port") pflag.Parse() viper.BindPFlags(pflag.CommandLine) fmt.Printf("ip :%s , port:%s", viper.GetString("ip"), viper.GetString("port")) }
命令行執(zhí)行上面程序:
# go run test.go --ip=192.168.7.3 --port=3306
可以看到輸出的是我們自定義的參數(shù)。
讀取環(huán)境變量參數(shù)
一般獲取環(huán)境變量使用os
包,比如:
getenv := os.Getenv("JAVA_HOME") fmt.Print(getenv)
Viper也提供了一種方式:
//表示 先預加載匹配的環(huán)境變量 viper.AutomaticEnv() //讀取已經(jīng)加載到default中的環(huán)境變量 if env := viper.Get("JAVA_HOME"); env == nil { println("error!") } else { fmt.Printf("%#v\n", env) }
由獲取環(huán)境變量我們是不是可以想到多環(huán)境參數(shù)配置呢?針對線上環(huán)境,開發(fā)環(huán)境分別加載不同yml中的參數(shù)。
func initConfig() (err error) { env := os.Getenv("GO_ENV") viper.SetConfigName(env) viper.AddConfigPath("./configs") viper.SetConfigType("yml") err = viper.ReadInConfig() return }
因為無論是線上環(huán)境還是測試環(huán)境,肯定有一些參數(shù)是公共不變的,那么這一部分參數(shù)是否可以抽出來作為一個單獨的配置文件呢。所以這樣配置文件可以分為兩個部分:
"github.com/gobuffalo/packr" func initConfig() (err error) { box := packr.NewBox("./configs") configType := "yml" defaultConfig, _ := box.Find("default.yml") v := viper.New() v.SetConfigType(configType) err = v.ReadConfig(bytes.NewReader(defaultConfig)) if err != nil { return } configs := v.AllSettings() // 將default中的配置全部以默認配置寫入 for k, v := range configs { viper.SetDefault(k, v) } env := os.Getenv("GO_ENV") // 根據(jù)配置的env讀取相應的配置信息 if env != "" { envConfig, _ := box.Find(env + ".yml") viper.SetConfigType(configType) err = viper.ReadConfig(bytes.NewReader(envConfig)) if err != nil { return } } return }
首先讀取default.yml中的參數(shù),將其寫入default中。然后再根據(jù)環(huán)境變量讀取不同環(huán)境中的參數(shù)。
這里使用了packr包,packr包的作用在于將靜態(tài)資源打包至應用程序中。
以上就是Go一站式配置管理工具Viper的使用教程的詳細內容,更多關于Go Viper的資料請關注腳本之家其它相關文章!
相關文章
Go+Kafka實現(xiàn)延遲消息的實現(xiàn)示例
本文主要介紹了Go+Kafka實現(xiàn)延遲消息的實現(xiàn)示例,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2022-07-07goland 實現(xiàn)websocket server的示例代碼
本文主要介紹了goland 實現(xiàn)websocket server的示例代碼,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2022-06-06