【Viper】配置格式與支持的數據源與go案例

Viper 是一個用于 Go 應用程序的配置管理庫,支持多種配置格式和數據源。


安裝依賴

go get github.com/spf13/viper
go get github.com/spf13/viper/remote
go get go.etcd.io/etcd/client/v3

"github.com/spf13/viper/remote"要寫在etcd客戶端import里

1. 配置格式—就是可以讀的配置類型

Viper 支持多種常見的配置格式,包括:

  • JSON: 一種輕量級的數據交換格式,易于閱讀和編寫。
  • YAML: 一種人類可讀的數據序列化格式,常用于配置文件。
  • TOML: 一種易于閱讀的配置文件格式,旨在成為最小的配置文件格式。
  • HCL: HashiCorp 配置語言,用于描述基礎設施配置。
  • Java Properties: 一種簡單的鍵值對格式,常用于 Java 應用程序。
  • INI: 一種簡單的配置文件格式,常用于 Windows 應用程序。
  • Envfile: 環境變量文件格式,通常用于存儲環境變量。

2. 支持的數據源—可以從哪里導入要讀的配置

Viper 不僅支持從文件中讀取配置,還支持從多種數據源獲取配置,包括:

  • 文件: 從本地文件系統中讀取配置文件。
  • 環境變量: 從操作系統的環境變量中讀取配置。
  • io.Reader: 從Reader中讀取配置。
  • 遠程配置系統: 從遠程配置系統(如 etcd、Consul)中讀取配置。

Viper 支持的四種常見數據源的簡單實現:

1. 文件

Viper 支持從多種文件格式中讀取配置,包括 JSON、YAML、TOML、HCL、INI 等。

使用方法

  • 設置配置文件路徑和名稱
    viper.SetConfigName("config") // 配置文件名稱(不帶擴展名)
    viper.SetConfigType("yaml")   // 配置文件類型(如 yaml、json 等)
    viper.AddConfigPath(".")      // 配置文件搜索路徑
    
  • 讀取配置文件
    if err := viper.ReadInConfig(); err != nil {log.Fatalf("Error reading config file: %s", err)
    }
    

示例

假設有一個 config.yaml 文件:

database:host: localhostport: 5432

讀取配置:

viper.SetConfigName("config")
viper.SetConfigType("yaml")
viper.AddConfigPath(".")
if err := viper.ReadInConfig(); err != nil {log.Fatal(err)
}
fmt.Println("Database Host:", viper.GetString("database.host"))
fmt.Println("Database Port:", viper.GetInt("database.port"))

2. 環境變量

Viper 可以從操作系統的環境變量中讀取配置,適合在容器化或云原生環境中使用。

使用方法

  • 啟用環境變量支持
    viper.AutomaticEnv() // 自動綁定環境變量
    
  • 設置環境變量前綴(可選):
    viper.SetEnvPrefix("MYAPP") // 環境變量前綴(如 MYAPP_DATABASE_HOST)
    
  • 綁定特定鍵到環境變量
    viper.BindEnv("database.host", "DB_HOST") // 將 database.host 綁定到環境變量 DB_HOST
    

示例

假設設置了環境變量:

export DB_HOST=localhost
export DB_PORT=5432

讀取配置:

viper.AutomaticEnv()
viper.BindEnv("database.host", "DB_HOST")
viper.BindEnv("database.port", "DB_PORT")
fmt.Println("Database Host:", viper.GetString("database.host"))
fmt.Println("Database Port:", viper.GetInt("database.port"))

3. io.Reader

Viper 支持從實現了 io.Reader 接口的對象中讀取配置,適合從內存或網絡流中加載配置。

使用方法

  • io.Reader 讀取配置
    configData := []byte(`{"database": {"host": "localhost", "port": 5432}}`)
    reader := bytes.NewReader(configData)
    viper.SetConfigType("json") // 設置配置類型
    if err := viper.ReadConfig(reader); err != nil {log.Fatal(err)
    }
    

示例

configData := []byte(`
database:host: localhostport: 5432
`)
reader := bytes.NewReader(configData)
viper.SetConfigType("yaml")
if err := viper.ReadConfig(reader); err != nil {log.Fatal(err)
}
fmt.Println("Database Host:", viper.GetString("database.host"))
fmt.Println("Database Port:", viper.GetInt("database.port"))

4. etcd

Viper 支持從 etcd(分布式鍵值存儲)中讀取配置,適合分布式系統的配置管理。

使用方法

  • 安裝 etcd 支持
    go get github.com/spf13/viper/remote
    
  • 配置 etcd 客戶端
    import ("github.com/spf13/viper"_ "github.com/spf13/viper/remote"
    )
    
  • 從 etcd 讀取配置
    viper.AddRemoteProvider("etcd", "http://127.0.0.1:2379", "/config/path")
    viper.SetConfigType("yaml") // 設置配置類型
    if err := viper.ReadRemoteConfig(); err != nil {log.Fatal(err)
    }
    

示例

假設 etcd 中存儲了以下配置:

database:host: localhostport: 5432

讀取配置:

viper.AddRemoteProvider("etcd", "http://127.0.0.1:2379", "/config/path")
viper.SetConfigType("yaml")
if err := viper.ReadRemoteConfig(); err != nil {log.Fatal(err)
}
fmt.Println("Database Host:", viper.GetString("database.host"))
fmt.Println("Database Port:", viper.GetInt("database.port"))

總結

  • 文件:適合本地開發和靜態配置。
  • 環境變量:適合容器化或云原生環境。
  • io.Reader:適合從內存或網絡流中加載配置。
  • etcd:適合分布式系統的動態配置管理。

綜合go案例

config.env

env=dev
server.ip=127.0.0.1
server.port=8080
courses=["golang", "C/C++", "音視頻", "kernel", "dpdk", "面試題", "游戲"]

config.json

{"env": "dev","server": {"ip":"127.0.0.1","port": 8085},"courses": ["golang","C/C++","音視頻","kernel","dpdk","面試題","游戲"],"list": [{"name": "golang","author": "nick"},{"name": "C/C++","author": "king"},{"name": "kernel","author": "vico"},{"name": "音視頻","author": "Darren"},{"name": "游戲","author": "mark"}]
}

config.noext

# 鍵值
env: dev
# 對象或map
server:ip: 127.0.0.1port: 8080
# 數組或列表
courses:- "golang"- "C/C++"- "音視頻"- "kernel"- "dpdk"- "面試題"- "游戲"list:- name: golangauthor: nick- name: C/C++author: king- name: kernelauthor: vico- name: 音視頻author: Darren- name: 游戲author: mark

config.yaml

# 鍵值
env: dev
# 對象或map
server:ip: 127.0.0.1port: 8080
# 數組或列表
courses:- "golang"- "C/C++"- "音視頻"- "kernel"- "dpdk"- "面試題"- "游戲"list:- name: golangauthor: nick- name: C/C++author: king- name: kernelauthor: vico- name: 音視頻author: Darren- name: 游戲author: mark

data_source.go

package configimport ("github.com/spf13/viper"_ "github.com/spf13/viper/remote""io""log"
)// LoadFromFile 加載配置文件。
// 該函數使用 vipers 去從指定的文件路徑加載配置。
// 參數:
//
//	filepath - 配置文件的路徑。
//	typ - 可選參數,指定配置文件的類型。
//
// 返回值:
//
//	*viper.Viper - 加載了配置文件數據的 viper 實例。
//	error - 如果加載配置文件時發生錯誤,返回該錯誤。
func LoadFromFile(filepath string, typ ...string) (*viper.Viper, error) {// 創建一個新的 viper 實例。v := viper.New()// 設置配置文件的路徑。v.SetConfigFile(filepath)// 如果提供了配置文件類型,則設置配置文件類型。if len(typ) > 0 {v.SetConfigType(typ[0])}// 讀取并解析配置文件到viper中。err := v.ReadInConfig()// 返回 viper 實例和可能的錯誤。return v, err
}// LoadFromEnv 初始化一個viper實例,并將其配置為自動從環境變量中加載配置。
// 該函數返回一個指向viper實例的指針,以及一個錯誤(此示例中未實現錯誤處理)。
func LoadFromEnv() (*viper.Viper, error) {// 創建一個新的viper實例。v := viper.New()// 啟用自動環境變量加載,viper將自動查找與結構體字段同名的環境變量。//v.AutomaticEnv()// 手動綁定環境變量GOPATH和GOROOT到viper實例。// 這樣做是為了方便地從環境變量中讀取這些值,而無需手動查詢環境變量。v.BindEnv("GOPATH")v.BindEnv("GOROOT")// 返回viper實例指針,以及nil作為錯誤值,表示沒有發生錯誤。return v, nil
}// LoadFromIoReader 從 io.Reader 類型的參數中加載配置信息。
// 此函數主要用于從不同的讀取源(如文件、網絡流等)中加載配置,
// 并根據提供的 typ 參數設置配置的類型。
// 參數:
//   - reader: io.Reader 類型的接口,代表任何可以讀取字節流的對象。
//   - typ: 字符串,指定配置文件的類型(例如 "json"、"yaml")。
//
// 返回值:
//   - *viper.Viper: 一個指向 viper.Viper 實例的指針,用于進一步操作或獲取配置信息。
//   - error: 在讀取配置過程中遇到的錯誤(如果有)。
func LoadFromIoReader(reader io.Reader, typ string) (*viper.Viper, error) {// 創建一個新的 viper 實例。v := viper.New()// 設置配置類型,根據傳入的 typ 參數。v.SetConfigType(typ)// 從 reader 參數指定的源中讀取配置信息。err := v.ReadConfig(reader)// 返回 viper 實例和可能的錯誤。return v, err
}// LoadFromEtcd loadFromEtcd 從 Etcd 中加載配置信息。
// 參數:
//
//	etcdAddr: Etcd服務器的地址。
//	key: 配置在Etcd中的鍵路徑。
//	typ: 配置文件的類型。
//
// 返回值:
//
//	*viper.Viper: 加載配置后的Viper實例指針。
//	error: 錯誤信息,如果有的話。
func LoadFromEtcd(etcdAddr, key, typ string) (*viper.Viper, error) {// 創建一個新的Viper實例。v := viper.New()// 為Viper實例添加Etcd3遠程提供者。// 這里可能會出現錯誤,如果提供的Etcd地址或鍵路徑無效。err := v.AddRemoteProvider("etcd3", etcdAddr, key)if err != nil {// 記錄錯誤信息。log.Println(err)// 返回nil和錯誤信息。return nil, err}// 設置Viper實例的配置類型。v.SetConfigType(typ)// 從遠程提供者讀取配置信息。// 這里可能會出現錯誤,如果無法從遠程提供者獲取配置信息。err = v.ReadRemoteConfig()// 返回Viper實例和可能的錯誤信息。return v, err
}

main.go

package mainimport ("bytes""context""fmt"clientv3 "go.etcd.io/etcd/client/v3""golang20-viper/config""log""os"
)func main() {//loadFile()//loadEnv()//loadReader()loadEtcd()
}// loadFile 函數演示了如何從不同格式的配置文件中加載配置。
// 它依次嘗試加載 .env, .json, .yaml, .toml 和 .yaml 文件,并打印出特定配置項的值。
func loadFile() {// 從 "config.env" 文件加載配置,并打印出環境、服務器端口和課程信息。v1, err := config.LoadFromFile("config.env", "env")fmt.Println("config.env", err, v1.Get("env"), v1.Get("server.port"), v1.Get("courses"))// 從 "config.json" 文件加載配置,包括環境、服務器端口、課程信息和作者信息。v2, err := config.LoadFromFile("config.json")fmt.Println("config.json", err, v2.Get("env"), v2.Get("server.port"), v2.Get("courses").([]any)[0], v2.Get("list").([]any)[0].(map[string]any)["author"])// 從 "config.noext" 文件加載 YAML 格式的配置,同樣打印環境、服務器端口、課程信息和作者信息。v3, err := config.LoadFromFile("config.noext", "yaml")fmt.Println("config.noext", err, v3.Get("env"), v3.Get("server.port"), v3.Get("courses").([]any)[0], v3.Get("list").([]any)[0].(map[string]any)["author"])// 從 "config.toml" 文件加載配置,展示如何獲取嵌套配置項的值。v4, err := config.LoadFromFile("config.toml")fmt.Println("config.toml", err, v4.Get("env"), v4.Get("server.port"), v4.Get("courses").(map[string]any)["list"].([]any)[0], v4.Get("list").([]any)[0].(map[string]any)["author"])// 從 "config.yaml" 文件加載配置,再次打印出環境、服務器端口、課程信息和作者信息,驗證不同格式文件的兼容性。v5, err := config.LoadFromFile("config.yaml")fmt.Println("config.yaml", err, v5.Get("env"), v5.Get("server.port"), v5.Get("courses").([]any)[0], v5.Get("list").([]any)[0].(map[string]any)["author"])
}func loadEnv() {v, err := config.LoadFromEnv()fmt.Println(err, v.Get("GOROOT"), v.Get("gopath"))
}// loadReader 讀取配置文件并解析特定配置項。
// 該函數沒有輸入參數和返回值。
// 功能描述:
// 1. 讀取名為 "config.yaml" 的配置文件。
// 2. 如果讀取過程中遇到錯誤,記錄錯誤信息并終止程序運行。
// 3. 使用 bytes.NewReader 創建一個字節流讀取器來讀取配置文件內容。
// 4. 調用 config.LoadFromIoReader 函數從字節流讀取器中加載配置信息。
// 5. 打印解析后的配置項,包括環境變量、服務器端口、課程信息和作者信息。
func loadReader() {// 讀取配置文件 "config.yaml" 的內容到 byteList。byteList, err := os.ReadFile("config.yaml")if err != nil {// 如果讀取配置文件時發生錯誤,記錄錯誤信息并終止程序。log.Fatalln(err)}// 創建一個新的字節流讀取器來讀取配置文件內容。r := bytes.NewReader(byteList)// 從字節流讀取器中加載配置信息,并處理可能的錯誤。v, err := config.LoadFromIoReader(r, "yaml")// 打印解析后的配置項。fmt.Println("io.reader", err, v.Get("env"), v.Get("server.port"), v.Get("courses").([]any)[0], v.Get("list").([]any)[0].(map[string]any)["author"])
}// loadEtcd 函數用于從本地文件加載配置并寫入到 etcd 中,然后從 etcd 中讀取配置并打印部分配置項。
// 該函數不接收任何參數,也不返回任何值。
func loadEtcd() {// 定義 etcd 的地址、配置項的鍵以及本地配置文件的路徑etcdAddr := "192.168.88.131:2379"key := "/0voice/viper/config.yaml"loaclFilepath := "config.yaml"// 將本地配置文件的內容寫入到 etcd 中writeConfToEtcd(etcdAddr, key, loaclFilepath)// 從 etcd 中加載配置,并解析為 yaml 格式v, err := config.LoadFromEtcd(etcdAddr, key, "yaml")// 打印從 etcd 中讀取的配置項,包括環境、服務器端口、課程列表中的第一個課程以及列表中的第一個作者的名稱fmt.Println("etcd", err, v.Get("env"), v.Get("server.port"), v.Get("courses").([]any)[0], v.Get("list").([]any)[0].(map[string]any)["author"])//fmt.Println(err, v)
}// writeConfToEtcd 將本地配置文件內容寫入到etcd指定鍵中
// 參數說明:
//   - etcdAddr: etcd服務地址,格式為"IP:PORT"
//   - key: etcd中存儲配置的鍵名
//   - localFilepath: 本地配置文件的路徑
//
// 功能說明:
//
//	讀取配置文件,將其內容存入etcd集群的指定鍵中
//	遇到任何錯誤(文件讀取、連接etcd、寫入etcd)將直接終止程序
func writeConfToEtcd(etcdAddr, key, localFilepath string) {// 從固定路徑讀取配置文件內容byteList, err := os.ReadFile(localFilepath)if err != nil {// 如果讀取配置文件時發生錯誤,記錄錯誤信息并終止程序。log.Fatalln(err)}v := string(byteList)// 創建etcd客戶端連接cli, err := clientv3.New(clientv3.Config{Endpoints: []string{etcdAddr},})if err != nil {log.Fatal(err)}// 將配置內容寫入etcd指定鍵_, err = cli.Put(context.Background(), key, v)if err != nil {log.Fatal(err)}
}

etcd docker部署

docker run -d \
-p 2379:2379 \
-p 2380:2380 \
--restart always \
--volume=/home/etcd:/etcd-data \
--name etcd quay.io/coreos/etcd:v3.5.7 \
/usr/local/bin/etcd \
--data-dir=/etcd-data --name node1 \
--initial-advertise-peer-urls http://192.168.239.161:2380 \
--listen-peer-urls http://0.0.0.0:2380 \
--advertise-client-urls http://192.168.239.161:2379 \
--listen-client-urls http://0.0.0.0:2379 \
--initial-cluster node1=http://192.168.239.161:2380 \
--initial-cluster-token tkn \
--initial-cluster-state new

https://github.com/0voice

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/895716.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/895716.shtml
英文地址,請注明出處:http://en.pswp.cn/news/895716.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

【C/C++】后綴表達式 藍橋杯/ACM備賽

核心考點:1.棧的應用 2.字符串處理 題目描述 所謂后綴表達式是指這樣的一個表達式:式中不再引用括號,運算符號放在兩個運算對象之后,所有計算按運算符號出現的順序,嚴格地由左而右新進行(不用考慮運算符的…

【AI實踐】deepseek支持升級git

當前Windows 11 WSL的git是2.17,Android Studio提示需要升級到2.19版本 網上找到指導文章 安裝git 2.19.2 cd /usr/src wget https://www.kernel.org/pub/software/scm/git/git-2.19.2.tar.gz tar xzf git-2.19.2.tar.gz cd git-2.19.2 make prefix/usr/l…

QEMU 搭建 Ubuntu x86 虛擬機

1. 安裝 QEMU 在 Ubuntu 系統中,可以通過以下命令安裝 QEMU: sudo apt-get update sudo apt-get install qemu-system-x86_64 qemu-kvm libvirt-daemon libvirt-clients bridge-utils virt-manager2. 創建虛擬硬盤鏡像 qemu-img create -f raw ubuntu…

Linux驅動層學習:Linux 設備樹

設備樹是一種數據結構,包含多個節點,用于描述硬件設備及其配置信息,它通常用于嵌入式系統中,尤其是在Linux操作系統中,幫助操作系統識別和管理硬件資源,設備樹不是代碼,而是一種用數據描述硬件信…

金蝶云星空與釘釘高效數據集成案例分享

金蝶云星空數據集成到釘釘的技術案例分享 在企業信息化系統中,數據的高效流動和實時反饋是提升業務效率的關鍵。本文將聚焦于一個具體的系統對接集成案例:如何將金蝶云星空的數據集成到釘釘,并實現審核狀態的回傳提示。 本次集成方案名為“…

圖形渲染(一)——Skia、OpenGL、Mesa 和 Vulkan簡介

1.Skia —— 2D 圖形庫 Skia 是一個 2D 圖形庫,它的作用是為開發者提供一個高層次的繪圖接口,方便他們進行 2D 圖形渲染(比如繪制文本、形狀、圖像等)。Skia 本身不直接管理 GPU 或進行底層的渲染工作,而是通過 底層圖…

GIT提錯分支,回滾提交

1. 準備示例 假設我們有三次提交: test1:需要在 master 分支提交test2、test3:需要在 develop 分支提交 遠端線上記錄 2. 步驟 選擇需要回退的記錄: 選中需要回退的 commit,選擇 Reset Current Branch to Here...。…

【原創】在ubuntu中搭建gradle開發環境

檢查Linux版本 rootwww:~# hostnamectlStatic hostname: www.0x88.comIcon name: computer-vmChassis: vmMachine ID: 30fa955a36be492ca459599ef20bc508Boot ID: 37084dbe36f44adaa075e8f9a98f132eVirtualization: kvm Operating System: Ubuntu 22.04.5 LTSKernel: Linux 5.…

【JavaEE進階】MyBatis入門

目錄 🌴前言 🌲什么是MyBatis? 🌳準備工作 🚩創建工程 🚩配置數據庫連接字符串 🚩數據準備 🚩編寫持久層代碼 🍃單元測試 🌴前言 在應?分層學習時,我們了解到…

以太網詳解(八)傳輸層協議:TCP/UDP 協議

文章目錄 傳輸層協議概述為什么需要傳輸層?傳輸層功能網絡層與傳輸層在實現 “端到端” 傳輸的異同兩類服務:面向連接/無連接服務 傳輸控制協議 TCPTCP 協議數據單元格式TCP 的重傳機制快重傳和快恢復快重傳舉例快恢復算法 用戶數據報協議 UDPUDP 概述UDP 基本工作過…

Electron 客戶端心跳定時任務調度庫調研文檔 - Node.js 任務調度庫技術調研文檔

Electron 客戶端心跳定時任務調度庫調研文檔 - Node.js 任務調度庫技術調研文檔 本文將對七個流行的定時任務調度庫:node-cron、rxjs、bull、node-schedule、agenda、bree、cron。這些庫都可以用來處理定時任務,但它們的特點和適用場景有所不同。我們將從…

DeepSeek 開放平臺無法充值 改用其他平臺API調用DeepSeek-chat模型方法

近幾天DeepSeek開放平臺無法充值目前已經關閉狀態,大家都是忙著接入DeepSeek模型 ,很多人想使用DeepSeek怎么辦? 當然還有改用其他平臺API調用方法,本文以本站的提供chatgpt系統為例,如何修改DeepSeek-chat模型API接口…

pix2text 使用經驗

給同行打雞血 😊 構建結構化的數理領域知識庫: 提高可訪問性和可搜索性 Markdown和LaTeX格式:這兩種格式易于在線發布和共享,有助于提高數學內容的可訪問性。搜索引擎優化:將PDF內容轉換為標記語言,可以…

Linux(centos)系統安裝部署MySQL8.0數據庫(GLIBC版本)

安裝前檢查服務器glibc版本,下載對應版本包 rpm -qa | grep glibc mysql安裝包及依賴包已整理好,下載地址:https://pan.quark.cn/s/3137acc814c0,下載即可安裝 一、下載MySQL mysql安裝包及依賴包已整理好,下載地址…

6.2.圖的存儲結構-鄰接矩陣法

一.鄰接矩陣法存儲不帶權圖: 結點不帶權值: 1.左圖的無向圖中,A到B直達的有一條路,所以A行B列的值為1; 左圖的無向圖中,A到F沒有直達的路,所以A行F列的值為0; 結論:無…

【VB語言】EXCEL中VB宏的應用

【VB語言】EXCEL中VB宏的應用 文章目錄 [TOC](文章目錄) 前言一、EXCEL-VB1.實驗過程2.代碼 二、EXCEL-VB 生成.c.h文件1.實驗過程2.代碼 四、參考資料總結 前言 1.WPS-VB擴展包 提示:以下是本篇文章正文內容,下面案例可供參考 一、EXCEL-VB 1.實驗過…

用deepseek學大模型05邏輯回歸

deepseek.com:邏輯回歸的目標函數,損失函數,梯度下降 標量和矩陣形式的數學推導,pytorch真實能跑的代碼案例以及模型,數據,預測結果的可視化展示, 模型應用場景和優缺點,及如何改進解決及改進方法數據推導。…

2025年02月17日Github流行趨勢

項目名稱:OmniParser 項目地址url:https://github.com/microsoft/OmniParser 項目語言:Jupyter Notebook 歷史star數:8971 今日star數:969 項目維護者:yadong-lu, ThomasDh-C, aliencaocao, nmstoker, kris…

RocketMQ 5.0安裝部署

0.前言 在微服務架構逐漸成為主流的今天,消息隊列如同數字世界的快遞員,承擔著系統間高效通信的重要使命。 Apache RocketMQ 自誕生以來,因其架構簡單、業務功能豐富、具備極強可擴展性等特點被眾多企業開發者以及云廠商廣泛采用。歷經十余…

Ubuntu 22.04.5 LTS 安裝企業微信,(2025-02-17安裝可行)

一、依賴包(Ubuntu 20.04/Debian 11) 點擊下載https://www.spark-app.store/download_dependencies_latest 1、 下載最新的依賴包。 請訪問星火應用商店依賴包下載頁面, 下載最新的依賴包。2、解壓依賴包 </