1. 程式人生 > 程式設計 >聊聊Golang中很好用的viper配置模組

聊聊Golang中很好用的viper配置模組

前言

viper 支援Yaml、Json、 TOML、HCL 等格式,讀取非常的方便。

安裝

go get github.com/spf13/viper

如果提示找不到golang.org/x/text/這個庫,是因為golang.org/x/text/這個庫在GitHub上託管的路徑不一致。

解決辦法:

可以從https://github.com/golang/text下載原始碼下來,然後到$GOPATH/src下面建立golang.org/x/資料夾(已存在的忽略),把壓縮包的檔案解壓到golang.org/x/資料夾之下。

然後執行 go install -x golang.org/x/text 即可解決:

正文

初始結構目錄如下:

聊聊Golang中很好用的viper配置模組

準備測試使用的yaml檔案,注意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檔案:

package main 
import (
 "github.com/spf13/viper"
 "fmt"
)
 
func main() {
 //讀取yaml檔案
 v := viper.New()
 //設定讀取的配置檔案
 v.SetConfigName("linux_config")
 //新增讀取的配置檔案路徑
 v.AddConfigPath("./config/")
 //windows環境下為%GOPATH,linux環境下為$GOPATH
 v.AddConfigPath("$GOPATH/src/")
 //設定配置檔案型別
 v.SetConfigType("yaml")
 
 if err := v.ReadInConfig();err != nil {
 fmt.Printf("err:%s\n",err)
 }
 
 fmt.Printf(
 `
 TimeStamp:%s
 CompanyInfomation.Name:%s
 CompanyInfomation.Department:%s `,v.Get("TimeStamp"),v.Get("CompanyInfomation.Name"),v.Get("CompanyInfomation.Department"),) 
 /*
 result:
 TimeStamp:2018-10-18 10:09:23
 CompanyInfomation.Name:Sunny
 CompanyInfomation.Department:[Finance Design Program Sales]
 */ 
}

也可以直接反序列化為Struct,非常的方便:

package main 
import (
 "github.com/spf13/viper"
 "fmt"
)
 
func main() {
 //讀取yaml檔案
 v := viper.New()
 //設定讀取的配置檔案
 v.SetConfigName("linux_config")
 //新增讀取的配置檔案路徑
 v.AddConfigPath("./config/")
 //windows環境下為%GOPATH,linux環境下為$GOPATH
 v.AddConfigPath("$GOPATH/src/")
 //設定配置檔案型別
 v.SetConfigType("yaml") 
 if err := v.ReadInConfig();err != nil {
 fmt.Printf("err:%s\n",err)
 }
 
 fmt.Printf( `
 TimeStamp:%s
 CompanyInfomation.Name:%s
 CompanyInfomation.Department:%s `,) 
 /*
 result:
 TimeStamp:2018-10-18 10:09:23
 CompanyInfomation.Name:Sunny
 CompanyInfomation.Department:[Finance Design Program Sales]
 */ 
 //反序列化
 parseYaml(v) 
}
 
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){
 var yamlObj YamlSetting;
 if err := v.Unmarshal(&yamlObj) ; err != nil{
 fmt.Printf("err:%s",err)
 }
 fmt.Println(yamlObj)
 /*
 result:
 {2018-10-18 10:09:23 Shenzhen 518000 {Sunny 50000000 200 [Finance Design Program Sales] false}}
 */
}

viper也提供了讀取Command Line引數的功能:

package main 
import (
 "github.com/spf13/pflag"
 "github.com/spf13/viper"
 "fmt"
)
 
func main() {
 pflag.String("hostAddress","127.0.0.1","Server running address")
 pflag.Int64("port",8080,"Server running port")
 pflag.Parse()
 
 viper.BindPFlags(pflag.CommandLine)
 fmt.Printf("hostAddress :%s,port:%s",viper.GetString("hostAddress"),viper.GetString("port"))
 /*
 example:
 go run main2.go --hostAddress=192.192.1.10 --port=9000
 help:
 Usage of /tmp/go-build183981952/b001/exe/main:
  --hostAddress string Server running address (default "127.0.0.1")
  --port int    Server running port (default 8080)
 */
 }

很多時候,我們伺服器啟動之後,如果臨時想修改某些配置引數,需要重啟伺服器才能生效,但是viper提供了監聽函式,可以免重啟修改配置引數,非常的實用:

package main 
import (
 "github.com/spf13/viper"
 "fmt"
 "golang.org/x/net/context"
 "github.com/fsnotify/fsnotify"
)
 
func main() {
 //讀取yaml檔案
 v := viper.New()
 //設定讀取的配置檔案
 v.SetConfigName("linux_config")
 //新增讀取的配置檔案路徑
 v.AddConfigPath("./config/")
 //windows環境下為%GOPATH,linux環境下為$GOPATH
 v.AddConfigPath("$GOPATH/src/")
 //設定配置檔案型別
 v.SetConfigType("yaml")
 
 if err := v.ReadInConfig(); err != nil {
 fmt.Printf("err:%s\n",err)
 }
 
 //建立一個通道等待關閉(模擬伺服器環境)
 ctx,_ := context.WithCancel(context.Background())
 //cancel可以關閉通道
 //ctx,cancel := context.WithCancel(context.Background())
 //設定監聽回撥函式
 v.OnConfigChange(func(e fsnotify.Event) {
 fmt.Printf("config is change :%s \n",e.String())
 //cancel()
 })
 //開始監聽
 v.WatchConfig()
 //通道不會主動關閉,可以主動呼叫cancel關閉
 <-ctx.Done()
 
 /*
 result:
 config is change :"/home/share/go/Viper/config/linux_config.yaml": CREATE 
 config is change :"/home/share/go/Viper/config/linux_config.yaml": CREATE
 */
}

完結

viper還有許多好用的功能,此文章只是舉例說明了很小的部分。

補充:viper-配置資訊處理框架(golang)

專案地址https://github.com/spf13/viper

1. viper

viper讀取配置資訊的優先順序順序,從高到底:

顯式呼叫Set函式

命令列引數

環境變數

配置檔案

key/value儲存系統

預設值

2. 設定值

(1)設定預設值

viper.SetDefault("ContentDir","content")

...

(2)讀取配置檔案

viper.SetConfigName("xxx")  // 設定配置檔名,不要帶字尾
viper.AddConfigPath("/path")  // 第一個搜尋路徑
viper.AddConfigPath("../etc")  // 設定為相對路徑
err := viper.ReadInConfig()  // 搜尋路徑,並讀取配置資料

(3)***監視配置檔案

viper支援應用程式執行時擁有讀取配置檔案的能力

viper例項通過WatchConfig函式:

viper.WatchConfig()
viper.OnConfigChange(func(e fsnotify.Event)) {
  fmt.Println("Config file changed:",e.Name)
})

(4)Set呼叫

viper.Set("Verbose",true)

viper.Set("LogFile",LogFile)

(5)繫結命令列引數

***viper支援繫結pflags引數【pflags是一個命令列引數解析庫】

serveCmd.Flags().Int("port",1138,"Port to run Application server on")

viper.BindPFlag("port",serverCmd.Flags().Lookup("port"))

3. 獲取值

Get(key string) : interface{}
GetBool(key string) : bool
GetFloat64(key string) : float64
GetInt(key string) : int
GetString(key string) : string
GetStringMap(key string) : map[string]interface{}
GetStringMapString(key string) : map[string]string
GetStringSlice(key string) : []string
GetTime(key string) : time.Time
GetDuration(key string) : time.Duration
IsSet(key string) : bool

以上為個人經驗,希望能給大家一個參考,也希望大家多多支援我們。如有錯誤或未考慮完全的地方,望不吝賜教。