一区二区三区在线-一区二区三区亚洲视频-一区二区三区亚洲-一区二区三区午夜-一区二区三区四区在线视频-一区二区三区四区在线免费观看

腳本之家,腳本語言編程技術及教程分享平臺!
分類導航

Python|VBS|Ruby|Lua|perl|VBA|Golang|PowerShell|Erlang|autoit|Dos|bat|

服務器之家 - 腳本之家 - Golang - golang常用庫之配置文件解析庫-viper使用詳解

golang常用庫之配置文件解析庫-viper使用詳解

2021-01-26 01:03九卷 Golang

viper 配置管理解析庫,是由大神 Steve Francia 開發,他在google領導著 golang 的產品開發,他也是 gohugo.io 的創始人之一,命令行解析庫 cobra 開發者,這篇文章主要介紹了golang常用庫之配置文件解析庫-viper使用詳解,需要的朋友可以參考

一、viper簡介

viper 配置管理解析庫,是由大神 Steve Francia 開發,他在google領導著 golang 的產品開發,他也是 gohugo.io 的創始人之一,命令行解析庫 cobra 開發者。總之,他在golang領域是專家,很牛的一個人。

他的github地址:https://github.com/spf13

viper是一個配置管理的解決方案,它能夠從 json,toml,ini,yaml,hcl,env 等多種格式文件中,讀取配置內容,它還能從一些遠程配置中心讀取配置文件,如consul,etcd等;它還能夠監聽文件的內容變化。

viper的 logo:

golang常用庫之配置文件解析庫-viper使用詳解

二、viper功能介紹

  • 讀取 json,toml,ini,yaml,hcl,env 等格式的文件內容
  • 讀取遠程配置文件,如 consul,etcd 等和監控配置文件變化
  • 讀取命令行 flag 的值
  • 從 buffer 中讀取值

配置文件又可以分為不同的環境,比如dev,test,prod等。

viper 可以幫助你專注配置文件管理。

viper 讀取配置文件的優先順序,從高到低,如下:

  • 顯式設置的Set函數
  • 命令行參數
  • 環境變量
  • 配置文件
  • 遠程k-v 存儲系統,如consul,etcd等
  • 默認值

Viper 配置key是不區分大小寫的。

其實,上面的每一種文件格式,都有一些比較有名的解析庫,如:

https://github.com/json-iterator/go
https://github.com/mailru/easyjson
https://github.com/bitly/go-simplejson
https://github.com/tidwall/gjson
ini : https://github.com/go-ini/ini
等等單獨文件格式解析庫。

但是為啥子要用viper,因為它是一個綜合文件解析庫,包含了上面所有的文件格式解析,是一個集合體,少了配置多個庫的煩惱。

三、viper使用

安裝viper命令:

?
1
go get github.com/spf13/viper

文檔: https://github.com/spf13/viper/blob/master/README.md#putting-values-into-viper

通過viper.Set設置值

如果某個鍵通過viper.Set設置了值,那么這個值讀取的優先級最高

?
1
viper.Set("mysql.info", "this is mysql info")

設置默認值

https://github.com/spf13/viper/blob/master/README.md#establishing-defaults

viper 支持默認值的設置。如果配置文件、環境變量、遠程配置中沒有設置鍵值,就可以通過viper設置一些默認值。

Examples:

?
1
2
3
viper.SetDefault("ContentDir", "content")
viper.SetDefault("LayoutDir", "layouts")
viper.SetDefault("Taxonomies", map[string]string{"tag": "tags", "category": "categories"})

讀取配置文件

https://github.com/spf13/viper/blob/master/README.md#reading-config-files

讀取配置文件說明

讀取配置文件要求:最少要知道從哪個位置查找配置文件。用戶一定要設置這個路徑。

viper可以從多個路徑搜索配置文件,單個viper實例只支持單個配置文件。
viper本身沒有設置默認的搜索路徑,需要用戶自己設置默認路徑。

viper搜索和讀取配置文件例子片段:

?
1
2
3
4
5
6
7
8
9
viper.SetConfigName("config") // 配置文件的文件名,沒有擴展名,如 .yaml, .toml 這樣的擴展名
viper.SetConfigType("yaml") // 設置擴展名。在這里設置文件的擴展名。另外,如果配置文件的名稱沒有擴展名,則需要配置這個選項
viper.AddConfigPath("/etc/appname/") // 查找配置文件所在路徑
viper.AddConfigPath("$HOME/.appname") // 多次調用AddConfigPath,可以添加多個搜索路徑
viper.AddConfigPath(".") // 還可以在工作目錄中搜索配置文件
err := viper.ReadInConfig() // 搜索并讀取配置文件
if err != nil { // 處理錯誤
 panic(fmt.Errorf("Fatal error config file: %s \n", err))
}

說明:
這里執行viper.ReadInConfig()之后,viper才能確定到底用哪個文件,viper按照上面的AddConfigPath() 進行搜索,找到第一個名為 config.ext (這里的ext代表擴展名: 如 json,toml,yaml,yml,ini,prop 等擴展名) 的文件后即停止搜索。

如果有多個名稱為config的配置文件,viper怎么搜索呢?它會按照如下順序搜索

  • config.json
  • config.toml
  • config.yaml
  • config.yml
  • config.properties (這種一般是java中的配置文件名)
  • config.props (這種一般是java中的配置文件名)

你還可以處理一些特殊情況:

?
1
2
3
4
5
6
7
8
9
if err := viper.ReadInConfig(); err != nil {
 if _, ok := err.(viper.ConfigFileNotFoundError); ok {
 // 配置文件沒有找到; 如果需要可以忽略
 } else {
 // 查找到了配置文件但是產生了其它的錯誤
 }
}
 
// 查找到配置文件并解析成功

注意[自1.6起]: 你也可以有不帶擴展名的文件,并以編程方式指定其格式。對于位于用戶$HOME目錄中的配置文件沒有任何擴展名,如.bashrc。

例子1. 讀取配置文件

config.toml 配置文件:

?
1
2
3
4
5
6
7
8
9
10
# this is a toml
 
title = "toml exaples"
redis = "127.0.0.1:3300" # redis
 
[mysql]
host = "192.168.1.1"
ports = 3306
username = "root"
password = "root123456"

viper_toml.go:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
package main
 
import(
 "fmt"
 "github.com/spf13/viper"
)
 
// 讀取配置文件config
type Config struct {
 Redis string
 MySQL MySQLConfig
}
 
type MySQLConfig struct {
 Port int
 Host string
 Username string
 Password string
}
 
func main() {
 // 把配置文件讀取到結構體上
 var config Config
 
 viper.SetConfigName("config")
 viper.AddConfigPath(".")
 err := viper.ReadInConfig()
 if err != nil {
 fmt.Println(err)
 return
 }
 
 viper.Unmarshal(&config) //將配置文件綁定到config上
 fmt.Println("config: ", config, "redis: ", config.Redis)
}

例子2. 讀取多個配置文件

在例子1基礎上多增加一個json的配置文件,config3.json 配置文件:

?
1
2
3
4
5
6
7
8
9
{
 "redis": "127.0.0.1:33000",
 "mysql": {
 "port": 3306,
 "host": "127.0.0.1",
 "username": "root",
 "password": "123456"
 }
}

viper_multi.go

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
package main
 
import (
    "fmt"
 
    "github.com/spf13/viper"
)
 
type Config struct {
    Redis string
    MySQL MySQLConfig
}
 
type MySQLConfig struct {
    Port int
    Host string
    Username string
    Password string
}
 
func main() {
    // 讀取 toml 配置文件
    var config1 Config
 
    vtoml := viper.New()
    vtoml.SetConfigName("config")
    vtoml.SetConfigType("toml")
    vtoml.AddConfigPath(".")
 
    if err := vtoml.ReadInConfig(); err != nil {
        fmt.Println(err)
        return
    }
 
    vtoml.Unmarshal(&config1)
    fmt.Println("read config.toml")
    fmt.Println("config: ", config1, "redis: ", config1.Redis)
 
    // 讀取 json 配置文件
    var config2 Config
    vjson := viper.New()
    vjson.SetConfigName("config3")
    vjson.SetConfigType("json")
    vjson.AddConfigPath(".")
 
    if err := vjson.ReadInConfig(); err != nil {
        fmt.Println(err)
        return
    }
 
    vjson.Unmarshal(&config2)
    fmt.Println("read config3.json")
    fmt.Println("config: ", config1, "redis: ", config1.Redis)
}

運行:

$ go run viper_multi.go

read config.toml
config: {127.0.0.1:33000 {0 192.168.1.1 root 123456}} redis: 127.0.0.1:33000
read config3.json
config: {127.0.0.1:33000 {0 192.168.1.1 root 123456}} redis: 127.0.0.1:33000

例子3. 讀取配置項的值

新建文件夾 item, 在里面創建文件 config.json,內容如下:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
{
 "redis": "127.0.0.1:33000",
 "mysql": {
 "port": 3306,
 "host": "127.0.0.1",
 "username": "root",
 "password": "123456",
 "ports": [
 5799,
 6029
 ],
 "metric": {
 "host": "127.0.0.1",
 "port": 2112
 }
 }
}

item/viper_get_item.go 讀取配置項的值

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
package main
 
import (
    "fmt"
 
    "github.com/spf13/viper"
)
 
func main() {
    viper.SetConfigName("config")
    viper.SetConfigType("json")
    viper.AddConfigPath(".")
    err := viper.ReadInConfig() //根據上面配置加載文件
    if err != nil {
        fmt.Println(err)
        return
    }
 
    host := viper.Get("mysql.host")
    username := viper.GetString("mysql.username")
    port := viper.GetInt("mysql.port")
    portsSlice := viper.GetIntSlice("mysql.ports")
 
    metricPort := viper.GetInt("mysql.metric.port")
    redis := viper.Get("redis")
 
    mysqlMap := viper.GetStringMapString("mysql")
 
    if viper.IsSet("mysql.host") {
        fmt.Println("[IsSet()]mysql.host is set")
    } else {
        fmt.Println("[IsSet()]mysql.host is not set")
    }
    fmt.Println("mysql - host: ", host, ", username: ", username, ", port: ", port)
    fmt.Println("mysql ports :", portsSlice)
    fmt.Println("metric port: ", metricPort)
    fmt.Println("redis - ", redis)
 
    fmt.Println("mysqlmap - ", mysqlMap, ", username: ", mysqlMap["username"])
}

運行:

$ go run viper_get_item.go

[IsSet()]mysql.host is set
mysql - host: 127.0.0.1 , username: root , port: 3306
mysql ports : [5799 6029]
metric port: 2112
redis - 127.0.0.1:33000
mysqlmap - map[host:127.0.0.1 metric: password:123456 port:3306 ports: username:root] , username: root

如果把上面的文件config.json寫成toml格式,怎么解析? 改成config1.toml:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
# toml
toml = "toml example"
 
redis = "127.0.0.1:33000"
 
[mysql]
port = 3306
host = "127.0.0.1"
username = "root"
password = "123456"
ports = [5799,6029]
[mysql.metric]
host = "127.0.0.1"
port = 2112

其實解析代碼差不多,只需修改2處,

viper.SetConfigName("config") 里的 config 改成 config1 ,
viper.SetConfigType("json")里的 json 改成 toml,其余代碼都一樣。解析的效果也一樣。

viper獲取值的方法:

  • Get(key string) : interface{}
  • GetBool(key string) : bool
  • GetFloat64(key string) : float64
  • GetInt(key string) : int
  • GetIntSlice(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
  • AllSettings() : map[string]interface{}

例子4. 讀取命令行的值

新建文件夾 cmd,然后cmd文件夾里新建config.json文件:

?
1
2
3
4
5
6
7
8
9
10
11
12
{
 "redis":{
 "port": 3301,
 "host": "127.0.0.1"
 },
 "mysql": {
 "port": 3306,
 "host": "127.0.0.1",
 "username": "root",
 "password": "123456"
 }
}

go解析文件,cmd/viper_pflag.go:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
package main
 
import (
    "fmt"
 
    "github.com/spf13/pflag"
    "github.com/spf13/viper"
)
 
func main() {
    pflag.Int("redis.port", 3302, "redis port")
 
    viper.BindPFlags(pflag.CommandLine)
    pflag.Parse()
 
    viper.SetConfigName("config")
    viper.SetConfigType("json")
    viper.AddConfigPath(".")
    err := viper.ReadInConfig() //根據上面配置加載文件
    if err != nil {
        fmt.Println(err)
        return
    }
 
    host := viper.Get("mysql.host")
    username := viper.GetString("mysql.username")
    port := viper.GetInt("mysql.port")
    redisHost := viper.GetString("redis.host")
    redisPort := viper.GetInt("redis.port")
 
    fmt.Println("mysql - host: ", host, ", username: ", username, ", port: ", port)
    fmt.Println("redis - host: ", redisHost, ", port: ", redisPort)
}

1.不加命令行參數運行:

$ go run viper_pflag.go

mysql - host: 127.0.0.1 , username: root , port: 3306
redis - host: 127.0.0.1 , port: 3301

說明:redis.port 的值是 3301,是 config.json 配置文件里的值。

2.加命令行參數運行

$ go run viper_pflag.go --redis.port 6666

mysql - host: 127.0.0.1 , username: root , port: 3306
redis - host: 127.0.0.1 , port: 6666

說明:加了命令行參數 --redis.port 6666,這時候redis.port輸出的值為 6666,讀取的是cmd命令行的值

例子5:io.Reader中讀取值

https://github.com/spf13/viper#reading-config-from-ioreader

viper_ioreader.go

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
package main
 
import (
    "bytes"
    "fmt"
 
    "github.com/spf13/viper"
)
 
func main() {
    viper.SetConfigType("yaml")
 
    var yaml = []byte(`
Hacker: true
name: steve
hobbies:
- skateboarding
- snowboarding
- go
clothing:
 jacket: leather
 trousers: denim
age: 35
eyes : brown
beard: true
 `)
 
    err := viper.ReadConfig(bytes.NewBuffer(yaml))
    if err != nil {
        fmt.Println(err)
        return
    }
    hacker := viper.GetBool("Hacker")
    hobbies := viper.GetStringSlice("hobbies")
    jacket := viper.Get("clothing.jacket")
    age := viper.GetInt("age")
    fmt.Println("Hacker: ", hacker, ",hobbies: ", hobbies, ",jacket: ", jacket, ",age: ", age)
 
}

例子6:寫配置文件

https://github.com/spf13/viper#writing-config-files

新建文件 writer/viper_write_config.go:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
package main
 
import (
    "fmt"
 
    "github.com/spf13/viper"
)
 
func main() {
    viper.SetConfigName("config")
    viper.SetConfigType("yaml")
    viper.AddConfigPath(".")
 
    viper.Set("yaml", "this is a example of yaml")
 
    viper.Set("redis.port", 4405)
    viper.Set("redis.host", "127.0.0.1")
 
    viper.Set("mysql.port", 3306)
    viper.Set("mysql.host", "192.168.1.0")
    viper.Set("mysql.username", "root123")
    viper.Set("mysql.password", "root123")
 
    if err := viper.WriteConfig(); err != nil {
        fmt.Println(err)
    }
}

運行:

$ go run viper_write_config.go

沒有任何輸出表示生成配置文件成功

?
1
2
3
4
5
6
7
8
9
mysql:
 host: 192.168.1.0
 password: root123
 port: 3306
 username: root123
redis:
 host: 127.0.0.1
 port: 4405
yaml: this is a example of yaml

WriteConfig() 和 SafeWriteConfig() 區別:

如果待生成的文件已經存在,那么SafeWriteConfig()就會報錯,Config File "config.yaml" Already Exists, 而WriteConfig()則會直接覆蓋同名文件。

四、參考

到此這篇關于golang常用庫之配置文件解析庫-viper使用詳解的文章就介紹到這了,更多相關golang配置文件解析庫viper內容請搜索服務器之家以前的文章或繼續瀏覽下面的相關文章希望大家以后多多支持服務器之家!

原文鏈接:https://www.cnblogs.com/jiujuan/p/13799976.html

延伸 · 閱讀

精彩推薦
  • Golanggo日志系統logrus顯示文件和行號的操作

    go日志系統logrus顯示文件和行號的操作

    這篇文章主要介紹了go日志系統logrus顯示文件和行號的操作,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧...

    SmallQinYan12302021-02-02
  • GolangGolang中Bit數組的實現方式

    Golang中Bit數組的實現方式

    這篇文章主要介紹了Golang中Bit數組的實現方式,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧...

    天易獨尊11682021-06-09
  • GolangGolang通脈之數據類型詳情

    Golang通脈之數據類型詳情

    這篇文章主要介紹了Golang通脈之數據類型,在編程語言中標識符就是定義的具有某種意義的詞,比如變量名、常量名、函數名等等,Go語言中標識符允許由...

    4272021-11-24
  • Golanggo語言制作端口掃描器

    go語言制作端口掃描器

    本文給大家分享的是使用go語言編寫的TCP端口掃描器,可以選擇IP范圍,掃描的端口,以及多線程,有需要的小伙伴可以參考下。 ...

    腳本之家3642020-04-25
  • Golanggolang json.Marshal 特殊html字符被轉義的解決方法

    golang json.Marshal 特殊html字符被轉義的解決方法

    今天小編就為大家分享一篇golang json.Marshal 特殊html字符被轉義的解決方法,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧 ...

    李浩的life12792020-05-27
  • Golanggolang如何使用struct的tag屬性的詳細介紹

    golang如何使用struct的tag屬性的詳細介紹

    這篇文章主要介紹了golang如何使用struct的tag屬性的詳細介紹,從例子說起,小編覺得挺不錯的,現在分享給大家,也給大家做個參考。一起跟隨小編過來看...

    Go語言中文網11352020-05-21
  • Golanggolang的httpserver優雅重啟方法詳解

    golang的httpserver優雅重啟方法詳解

    這篇文章主要給大家介紹了關于golang的httpserver優雅重啟的相關資料,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,...

    helight2992020-05-14
  • Golanggolang 通過ssh代理連接mysql的操作

    golang 通過ssh代理連接mysql的操作

    這篇文章主要介紹了golang 通過ssh代理連接mysql的操作,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧...

    a165861639710342021-03-08
主站蜘蛛池模板: 性色AV乱码一区二区三区视频 | 青青青青久久国产片免费精品 | 男女小视频在线观看 | 秀婷程仪公欲息肉婷在线观看 | 青青视频国产依人在线 | 456在线观看 | 国产愉拍 | 黄a级| 美女的隐私无遮挡撒尿 | 手机在线伦理片 | 女同久久另类99精品国产 | 免费片在线观看 | porono日本人xxx| 欧美亚洲一区二区三区 | 香蕉91xj.cc| 久久综合网久久综合 | 亚洲 欧美 国产 综合 在线 | 亚洲va国产日韩欧美精品色婷婷 | 国产精品原创永久在线观看 | 男人狂躁女人下面的视频免费 | 四虎1515hhc0m | 荡女人人爱全文免费阅读 | 床戏小说 | 青青草国产免费国产是公开 | 男女xxoo做爰猛烈动态一 | 99在线观看视频免费 | 拔插拔插.com | 亚洲福利 影院 | 亚洲欧洲综合 | 久久不射网| 女暴露狂校园裸露小说 | 999任你躁在线精品免费不卡 | vod国产成人精品视频 | 国产 日韩 欧美 综合 | 图片亚洲va欧美va国产综合 | 好 舒服 好 粗 好硬免费视频 | 白丝校花掀起短裙呻吟小说 | 国产精品久久久久毛片 | 日本高清中文字幕一区二区三区 | 国产一区二区三区福利 | 色婷婷六月天 |