最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

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

 更新時(shí)間:2020年10月16日 09:19:49   作者:九卷  
viper 配置管理解析庫,是由大神 Steve Francia 開發(fā),他在google領(lǐng)導(dǎo)著 golang 的產(chǎn)品開發(fā),他也是 gohugo.io 的創(chuàng)始人之一,命令行解析庫 cobra 開發(fā)者,這篇文章主要介紹了golang常用庫之配置文件解析庫-viper使用詳解,需要的朋友可以參考下

golang常用庫:gorilla/mux-http路由庫使用
golang常用庫:配置文件解析庫-viper使用
golang常用庫:操作數(shù)據(jù)庫的orm框架-gorm基本使用
golang常用庫:字段參數(shù)驗(yàn)證庫-validator使用

一、viper簡介

viper 配置管理解析庫,是由大神 Steve Francia 開發(fā),他在google領(lǐng)導(dǎo)著 golang 的產(chǎn)品開發(fā),他也是 gohugo.io 的創(chuàng)始人之一,命令行解析庫 cobra 開發(fā)者??傊?,他在golang領(lǐng)域是專家,很牛的一個(gè)人。

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

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

viper的 logo:

二、viper功能介紹

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

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

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

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

  • 顯式設(shè)置的Set函數(shù)
  • 命令行參數(shù)
  • 環(huán)境變量
  • 配置文件
  • 遠(yuǎn)程k-v 存儲(chǔ)系統(tǒng),如consul,etcd等
  • 默認(rèn)值

Viper 配置key是不區(qū)分大小寫的。

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

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
等等單獨(dú)文件格式解析庫。

但是為啥子要用viper,因?yàn)樗且粋€(gè)綜合文件解析庫,包含了上面所有的文件格式解析,是一個(gè)集合體,少了配置多個(gè)庫的煩惱。

三、viper使用

安裝viper命令:

go get github.com/spf13/viper

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

通過viper.Set設(shè)置值

如果某個(gè)鍵通過viper.Set設(shè)置了值,那么這個(gè)值讀取的優(yōu)先級(jí)最高

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

設(shè)置默認(rèn)值

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

viper 支持默認(rèn)值的設(shè)置。如果配置文件、環(huán)境變量、遠(yuǎn)程配置中沒有設(shè)置鍵值,就可以通過viper設(shè)置一些默認(rèn)值。

Examples:

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

讀取配置文件說明

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

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

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

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

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

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

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

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

if err := viper.ReadInConfig(); err != nil {
 if _, ok := err.(viper.ConfigFileNotFoundError); ok { 
 // 配置文件沒有找到; 如果需要可以忽略
 } else { 
 // 查找到了配置文件但是產(chǎn)生了其它的錯(cuò)誤
 }
}

// 查找到配置文件并解析成功

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

例子1. 讀取配置文件

config.toml 配置文件:

# 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:

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() {
 // 把配置文件讀取到結(jié)構(gòu)體上
 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. 讀取多個(gè)配置文件

在例子1基礎(chǔ)上多增加一個(gè)json的配置文件,config3.json 配置文件:

{
 "redis": "127.0.0.1:33000",
 "mysql": {
 "port": 3306,
 "host": "127.0.0.1",
 "username": "root",
 "password": "123456"
 }
}

viper_multi.go

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)
}

運(yùn)行:

$ 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. 讀取配置項(xiàng)的值

新建文件夾 item, 在里面創(chuàng)建文件 config.json,內(nèi)容如下:

{
 "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 讀取配置項(xiàng)的值

package main

import (
	"fmt"

	"github.com/spf13/viper"
)

func main() {
	viper.SetConfigName("config")
	viper.SetConfigType("json")
	viper.AddConfigPath(".")
	err := viper.ReadInConfig() //根據(jù)上面配置加載文件
	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"])
}

運(yùn)行:

$ 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:

# 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

其實(shí)解析代碼差不多,只需修改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文件:

{
 "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:

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() //根據(jù)上面配置加載文件
	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.不加命令行參數(shù)運(yùn)行:

$ 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.加命令行參數(shù)運(yùn)行

$ 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

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

例子5:io.Reader中讀取值

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

viper_ioreader.go

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:

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)
	}
}

運(yùn)行:

$ go run viper_write_config.go

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

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() 區(qū)別:

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

四、參考

到此這篇關(guān)于golang常用庫之配置文件解析庫-viper使用詳解的文章就介紹到這了,更多相關(guān)golang配置文件解析庫viper內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • golang并發(fā)鎖使用詳解

    golang并發(fā)鎖使用詳解

    這篇文章主要介紹了golang并發(fā)鎖使用詳解的相關(guān)資料,需要的朋友可以參考下
    2023-02-02
  • grom設(shè)置全局日志實(shí)現(xiàn)執(zhí)行并打印sql語句

    grom設(shè)置全局日志實(shí)現(xiàn)執(zhí)行并打印sql語句

    本文主要介紹了grom設(shè)置全局日志實(shí)現(xiàn)執(zhí)行并打印sql語句,包括設(shè)置日志級(jí)別、實(shí)現(xiàn)自定義Logger接口以及如何使用GORM的默認(rèn)logger,通過這些方法,可以更好地控制和記錄數(shù)據(jù)庫操作的日志信息
    2025-03-03
  • Go通過不變性優(yōu)化程序詳解

    Go通過不變性優(yōu)化程序詳解

    這篇文章主要為大家介紹了Go通過不變性優(yōu)化程序?qū)嵗斀猓行枰呐笥芽梢越梃b參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-08-08
  • Go語言的變量定義詳情

    Go語言的變量定義詳情

    這篇文章主要介紹了Go語言的變量定義詳情,go定義變量的方式和c,c++,java語法不一樣,var?變量名類型,var在前,變量名在中間,類型在后面,下文更多詳細(xì)內(nèi)容需要的小伙伴可以參考一下
    2022-03-03
  • Go設(shè)計(jì)模式之備忘錄模式講解和代碼示例

    Go設(shè)計(jì)模式之備忘錄模式講解和代碼示例

    備忘錄是一種行為設(shè)計(jì)模式, 允許生成對(duì)象狀態(tài)的快照并在以后將其還原,本文就通過代碼示例給大家講講Go備忘錄模式,感興趣的小伙伴跟著小編一起來看看吧
    2023-08-08
  • vim配置go語言語法高亮問題的解決方法

    vim配置go語言語法高亮問題的解決方法

    vim配置go語言語法高亮的問題已經(jīng)遇到過好幾次了,每次都是找不到答案,今天小編給大家?guī)砹藇im配置go語言語法高亮問題的解決方法,感興趣的朋友一起看看吧
    2018-01-01
  • 一文搞懂Go語言中文件的讀寫與創(chuàng)建

    一文搞懂Go語言中文件的讀寫與創(chuàng)建

    這篇文章主要為大家詳細(xì)介紹了Go語言中文件是如何實(shí)現(xiàn)讀寫與創(chuàng)建的,文中的示例代碼講解詳細(xì),對(duì)我們學(xué)習(xí)Go語言有一定幫助,需要的可以參考一下
    2022-07-07
  • Go逃逸分析示例詳解

    Go逃逸分析示例詳解

    這篇文章主要為大家介紹了Go逃逸分析示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-08-08
  • Go語言開發(fā)技巧必知的小細(xì)節(jié)提升效率

    Go語言開發(fā)技巧必知的小細(xì)節(jié)提升效率

    這篇文章主要介紹了Go語言開發(fā)技巧必知的小細(xì)節(jié)提升效率,分享幾個(gè)你可能不知道的Go語言小細(xì)節(jié),希望能幫助大家更好地學(xué)習(xí)這門語言
    2024-01-01
  • Golang中多個(gè)if代碼優(yōu)化小技巧

    Golang中多個(gè)if代碼優(yōu)化小技巧

    這篇文章主要為大家詳細(xì)介紹了Golang中一些常用的if代碼優(yōu)化小技巧,w文中的示例代碼簡潔易懂,具有一定的借鑒價(jià)值,感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下
    2023-10-10

最新評(píng)論

阿克陶县| 鄯善县| 土默特左旗| 太原市| 牟定县| 葵青区| 连山| 崇义县| 恭城| 玛曲县| 饶河县| 卓尼县| 隆化县| 塔城市| 赤峰市| 正宁县| 天峨县| 樟树市| 定襄县| 西安市| 易门县| 历史| 准格尔旗| 包头市| 平安县| 民丰县| 西平县| 武清区| 沙坪坝区| 玉溪市| 淮北市| 德州市| 沙湾县| 宝丰县| 定兴县| 红原县| 永兴县| 桂平市| 阜城县| 安阳市| 江川县|