亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

Go語(yǔ)言項(xiàng)目中使用Viper獲取配置信息詳解

 更新時(shí)間:2024年04月02日 08:15:24   作者:仍沫  
Viper是Go應(yīng)用的完整配置解決方案,它能處理所有類型的配置需求和配置格式,這篇文章主要介紹了Go項(xiàng)目中使用Viper獲取配置信息,需要的可以參考下

Viper是Go應(yīng)用的完整配置解決方案,它能處理所有類型的配置需求和配置格式,支持:

  • 設(shè)置默認(rèn)值。
  • 讀取JSON、TOML、YAML、HCL、envfile和Java屬性配置文件。
  • 實(shí)時(shí)觀察和重新讀取配置(可選)。
  • 讀取環(huán)境變量。
  • 從遠(yuǎn)程配置系統(tǒng)(etcd或Consul)讀取配置,并觀察其變化。
  • 從命令行標(biāo)志讀取配置。
  • 從緩沖區(qū)讀取配置。
  • 設(shè)置顯式值。

Viper的優(yōu)先級(jí)順序是:顯式調(diào)用Set > 命令行標(biāo)志 > 環(huán)境變量 > 配置文件 > 鍵/值 存儲(chǔ)(etcd或Consul) > 默認(rèn)值。

本文主要記錄從yaml文件、環(huán)境變量中獲取配置。

使用的go的版本和viper的版本如下:

go 1.20
github.com/spf13/viper v1.18.2

從配置文件中獲取配置

執(zhí)行以下指令初始化項(xiàng)目:

go mod init github.com/rengmo/practicego

執(zhí)行以下語(yǔ)句安裝viper包:

go get github.com/spf13/viper

創(chuàng)建yaml文件config/dev.yaml,內(nèi)容如下:

redis:
  host: localhost
  port: 6379
  user:     # 本地redis的用戶名為空
  password: abc123
  db: 0

創(chuàng)建Go文件infrastructure/config.go,內(nèi)容如下:

package config

import (
	"fmt"

	"github.com/spf13/viper"
)

func init() {
	// 設(shè)置配置文件的名字
	viper.SetConfigName("dev")
	// 設(shè)置文件的格式
	viper.SetConfigType("yaml")
	// 設(shè)置查找配置文件的路徑為當(dāng)前路徑 . 表示項(xiàng)目的工作目錄,也就是main.go同級(jí)的那個(gè)目錄
	viper.AddConfigPath("./config")

	// 讀取配置文件中的數(shù)據(jù)到viper中
	err := viper.ReadInConfig()
	if err != nil {
		panic(err)
	}
	// 從viper中獲取配置數(shù)據(jù)
	redisPort := viper.Get("redis.port")
	fmt.Printf("redisPort: %v \n", redisPort) // 打印結(jié)果:redisPort: 6379 
}

還可以使用GetInt()、GetString()等方法,獲取指定類型的數(shù)據(jù),viper.GetString("redis.port")就是獲取字符串類型的數(shù)據(jù)。

創(chuàng)建main.go文件,內(nèi)容如下:

package main

import (
	_ "github.com/rengmo/practicego/infrastructure"
)

func main() {

}

運(yùn)行代碼,會(huì)打印出獲取到的端口號(hào)。

	// 設(shè)置配置文件的名字
	viper.SetConfigName("dev")
	// 設(shè)置文件的格式
	viper.SetConfigType("yaml")
	// 設(shè)置查找配置文件的路徑為當(dāng)前路徑 . 表示項(xiàng)目的工作目錄,也就是main.go同級(jí)的那個(gè)目錄
	viper.AddConfigPath("./config")

換成:

// 設(shè)置配置文件的路徑
viper.SetConfigFile("./config/dev.yaml")

同樣能取到配置文件中的數(shù)據(jù)。

除了使用Get方法viper.Get("redis.port")獲取配置數(shù)據(jù),還可以將配置數(shù)據(jù)反序列化成Go對(duì)象。

func init() {
  ...
	var config *Config
	err = viper.Unmarshal(&config)
	if err != nil {
		panic(err)
	}
	redisConfig := config.Redis
	fmt.Printf("redisConfig %+v\n", redisConfig) 
  // 打印的結(jié)果:redisConfig {Host:localhost Port:6379 User: Password:abc123 DB:0}
}

type Config struct {
	Redis RedisConfig
}

type RedisConfig struct {
	Host     string
	Port     int
	User     string
	Password string
	DB       int
}

Viper對(duì)于配置項(xiàng)的鍵是不區(qū)分大小寫的,比如把yaml文件中的鍵改成首字母大寫:

Redis:
  Host: localhost
  Port: 6379

使用viper.Get("redis.port")一樣能獲取到配置的值,使用viper.Get("REDIS.PORT")同樣能獲取配置的值。

從環(huán)境變量中獲取配置

AutomaticEnv會(huì)檢查環(huán)境變量中是否有和已經(jīng)存在的鍵匹配的環(huán)境變量,如果有,就會(huì)把環(huán)境變量加載到viper中。

// AutomaticEnv makes Viper check if environment variables match any of the existing keys
// (config, default or flags). If matching env vars are found, they are loaded into Viper.
func AutomaticEnv() { v.AutomaticEnv() }

先在終端執(zhí)行指令添加環(huán)境變量: export env=PROD,然后在終端執(zhí)行go run .。

光看這個(gè)函數(shù)名稱,是自動(dòng)將環(huán)境變量添加到viper中的意思,那么執(zhí)行下面的語(yǔ)句應(yīng)該就能獲取環(huán)境變量,但是無(wú)效:

	viper.AutomaticEnv()
	env := viper.Get("env")
	fmt.Println("env: ", env) // env:  <nil>

根據(jù)函數(shù)注釋,需要確認(rèn)viper中是否已經(jīng)有對(duì)應(yīng)的鍵,那么執(zhí)行下面的語(yǔ)句應(yīng)該就能獲取環(huán)境變量,但是依然無(wú)效:

	viper.SetDefault("env", "DEV")
	viper.AutomaticEnv()
	env := viper.Get("env")
	fmt.Println("env: ", env) // env:  DEV

找了一下源碼,判斷鍵是否存在的地方使用了envkeys, exists := v.env[lcaseKey],而BindEnv方法中有設(shè)置v.env

func (v *Viper) BindEnv(input ...string) error {
	if len(input) == 0 {
		return fmt.Errorf("missing key to bind to")
	}

	key := strings.ToLower(input[0])

	if len(input) == 1 {
		v.env[key] = append(v.env[key], v.mergeWithEnvPrefix(key))
	} else {
		v.env[key] = append(v.env[key], input[1:]...)
	}

	return nil
}

所以需要這樣使用:

	viper.BindEnv("env", "DEV")
	viper.AutomaticEnv()
	env := viper.Get("env")
	fmt.Println("env: ", env) // env:  PROD

要注意在比較過(guò)程中,Viper會(huì)把key轉(zhuǎn)換成大寫字母與環(huán)境變量進(jìn)行比較,所以環(huán)境變量的名稱必須為大寫,不能這樣設(shè)置環(huán)境變量:export env=PROD,必須這樣設(shè)置環(huán)境變量:export ENV=PROD

其他

如果是使用編輯器來(lái)運(yùn)行代碼,需要在編輯器中設(shè)置環(huán)境變量,我用的是VSCode編輯器,所以是在launch.json中添加了環(huán)境變量:

{
    // Use IntelliSense to learn about possible attributes.
    // Hover to view descriptions of existing attributes.
    // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
    "version": "0.2.0",
    "configurations": [
        {
            "name": "Launch Package",
            "type": "go",
            "request": "launch",
            "mode": "auto",
            "program": "${workspaceFolder}",
            "env": {
                "env": "PROD"
            }
        }
    ]
}

序列化和反序列化時(shí),可以使用 mapstructure指定鍵的名稱。

比如yaml文件內(nèi)容:

mysql:
  host: localhost
  port: 3306
  user: root
  password: 666666Aa_
  db_name: practicego

go文件內(nèi)容:

type Config struct {
	Redis    RedisConfig
	MySQL    MySQLConfig
	Priority string
}

type MySQLConfig struct {
	Host     string
	Port     int
	User     string
	Password string
	DBName   string `mapstructure:"db_name"`
}

func init() {
	viper.SetConfigFile("./config/dev.yaml")
	err := viper.ReadInConfig()
	if err != nil {
		panic(err)
	}
  
  var config *Config
	err = viper.Unmarshal(&config)
	if err != nil {
		panic(err)
	}
  
  mysqlConfig := config.MySQL
	fmt.Printf("mysqlConfig %+v\n", mysqlConfig)
}

以上就是Go語(yǔ)言項(xiàng)目中使用Viper獲取配置信息詳解的詳細(xì)內(nèi)容,更多關(guān)于Go Viper獲取配置信息的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

最新評(píng)論