Go一站式配置管理工具Viper的使用教程
什么是Viper
Viper是一個(gè)方便Go語言應(yīng)用程序處理配置信息的庫。它可以處理多種格式的配置。它支持的特性:
- 設(shè)置默認(rèn)值
- 從JSON、TOML、YAML、HCL和Java properties文件中讀取配置數(shù)據(jù)
- 可以監(jiān)視配置文件的變動(dòng)、重新讀取配置文件
- 從環(huán)境變量中讀取配置數(shù)據(jù)
- 從遠(yuǎn)端配置系統(tǒng)中讀取數(shù)據(jù),并監(jiān)視它們(比如etcd、Consul)
- 從命令參數(shù)中讀物配置
- 從buffer中讀取
- 調(diào)用函數(shù)設(shè)置配置信息
為什么要使用Viper
在構(gòu)建現(xiàn)代應(yīng)用程序時(shí),您不必?fù)?dān)心配置文件格式; 你可以專注于構(gòu)建出色的軟件。
Viper 可以做如下工作:
- 加載并解析JSON、TOML、YAML、HCL 或 Java properties 格式的配置文件
- 可以為各種配置項(xiàng)設(shè)置默認(rèn)值
- 可以在命令行中指定配置項(xiàng)來覆蓋配置值
- 提供了別名系統(tǒng),可以不破壞現(xiàn)有代碼來實(shí)現(xiàn)參數(shù)重命名
- 可以很容易地分辨出用戶提供的命令行參數(shù)或配置文件與默認(rèn)相同的區(qū)別
Viper讀取配置信息的優(yōu)先級順序,從高到低,如下:
- 顯式調(diào)用Set函數(shù)
- 命令行參數(shù)
- 環(huán)境變量
- 配置文件
- key/value 存儲系統(tǒng)
- 默認(rèn)值
Viper 的配置項(xiàng)的key不區(qū)分大小寫。
項(xiàng)目地址:https://github.com/spf13/viper
使用
設(shè)置默認(rèn)值
默認(rèn)值不是必須的,如果配置文件、環(huán)境變量、遠(yuǎn)程配置系統(tǒng)、命令行參數(shù)、Set函數(shù)都沒有指定時(shí),默認(rèn)值將起作用。
viper.SetDefault("name", "xiaoming") viper.SetDefault("age", "12") viper.SetDefault("notifyList", []string{"xiaohong","xiaoli","xiaowang"})
讀取配置文件
Viper支持JSON、TOML、YAML、HCL和Java properties文件。
Viper可以搜索多個(gè)路徑,但目前單個(gè)Viper實(shí)例僅支持單個(gè)配置文件。
Viper默認(rèn)不搜索任何路徑。
以下是如何使用Viper搜索和讀取配置文件的示例。
路徑不是必需的,但最好至少應(yīng)提供一個(gè)路徑,以便找到一個(gè)配置文件。
viper.SetConfigName("dbConfig") // 設(shè)置配置文件名 (不帶后綴) viper.AddConfigPath("/workspace/appName/") // 第一個(gè)搜索路徑 viper.AddConfigPath("/workspace/appName1") // 可以多次調(diào)用添加路徑 viper.AddConfigPath(".") // 比如添加當(dāng)前目錄 err := viper.ReadInConfig() // 搜索路徑,并讀取配置數(shù)據(jù) if err != nil { panic(fmt.Errorf("Fatal error config file: %s \n", err)) }
監(jiān)視配置文件,重新讀取配置數(shù)據(jù)
Viper支持讓你的應(yīng)用程序在運(yùn)行時(shí)擁有讀取配置文件的能力。
只需要調(diào)用viper實(shí)例的WatchConfig函數(shù),你也可以指定一個(gè)回調(diào)函數(shù)來獲得變動(dòng)的通知。
viper.WatchConfig() viper.OnConfigChange(func(e fsnotify.Event) { fmt.Println("Config file changed:", e.Name) })
從 io.Reader 中讀取配置
Viper預(yù)先定義了許多配置源,例如文件、環(huán)境變量、命令行參數(shù)和遠(yuǎn)程K / V存儲系統(tǒng)。也可以實(shí)現(xiàn)自己的配置源,并提供給viper。
現(xiàn)在有如下yaml文件:
userName: "xiaoming" address: "廣州市XXX" sex: 1 company: name: "xxx" employeeId: 1000 department: - "技術(shù)部"
讀取文件的代碼如下:
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() //設(shè)置讀取的配置文件名 v.SetConfigName("userInfo") //windows環(huán)境下為%GOPATH,linux環(huán)境下為$GOPATH v.AddConfigPath("/Users/yangyue/workspace/go/src/webDemo/") //設(shè)置配置文件類型 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;第二種你可以手動(dòng)的反序列化為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也提供了一種方式:
//表示 先預(yù)加載匹配的環(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 }
因?yàn)闊o論是線上環(huán)境還是測試環(huán)境,肯定有一些參數(shù)是公共不變的,那么這一部分參數(shù)是否可以抽出來作為一個(gè)單獨(dú)的配置文件呢。所以這樣配置文件可以分為兩個(gè)部分:
"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中的配置全部以默認(rèn)配置寫入 for k, v := range configs { viper.SetDefault(k, v) } env := os.Getenv("GO_ENV") // 根據(jù)配置的env讀取相應(yīng)的配置信息 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)資源打包至應(yīng)用程序中。
以上就是Go一站式配置管理工具Viper的使用教程的詳細(xì)內(nèi)容,更多關(guān)于Go Viper的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
golang MarshalJson的實(shí)現(xiàn)
本文主要介紹了golang MarshalJson的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2025-03-03Golang棧結(jié)構(gòu)和后綴表達(dá)式實(shí)現(xiàn)計(jì)算器示例
這篇文章主要為大家介紹了Golang棧結(jié)構(gòu)和后綴表達(dá)式實(shí)現(xiàn)計(jì)算器示例,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-07-07Go+Kafka實(shí)現(xiàn)延遲消息的實(shí)現(xiàn)示例
本文主要介紹了Go+Kafka實(shí)現(xiàn)延遲消息的實(shí)現(xiàn)示例,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2022-07-07goland 實(shí)現(xiàn)websocket server的示例代碼
本文主要介紹了goland 實(shí)現(xiàn)websocket server的示例代碼,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2022-06-06golang切片擴(kuò)容規(guī)則實(shí)現(xiàn)
這篇文章主要介紹了golang切片擴(kuò)容規(guī)則實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2021-03-03Go語言基礎(chǔ)模板設(shè)計(jì)模式示例詳解
這篇文章主要為大家介紹了Go語言基礎(chǔ)設(shè)計(jì)模式之模板模式的示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步2021-11-11