一個小例子,給你講透 Go 配置管理,輕鬆將其融入到項目中
在軟件開發中,配置管理是一個不可或缺的部分。無論是開發環境、測試環境還是生產環境,我們都需要一種方法來存儲和讀取配置信息。
在 Golang 項目中,Viper 是一個非常流行且功能強大的庫,用於處理配置文件。下面我會寫一些例子,幫助大家快速上手。
什麼是 Viper?
不賣關子,直接上 GitHub 地址:https://github.com/spf13/viper 大家可以直接去看 README.md。
我簡單的描述下,Viper 是一個 Go 語言的配置管理庫,它提供了簡單而強大的方式來處理應用程序的配置需求。無論是從文件、環境變量還是遠程配置中獲取配置信息,Viper 都能搞定。
如何使用 Viper?
安裝
在終端中運行以下命令:
go get github.com/spf13/viper
基本用法
以下是一個簡單的示例,展示如何讀取配置文件:
package main
import (
"fmt"
"github.com/spf13/viper"
)
func main() {
// 設置配置文件名稱(不包括文件擴展名)
viper.SetConfigName("config")
// 設置配置文件類型
viper.SetConfigType("toml")
// 添加配置文件搜索路徑
viper.AddConfigPath(".")
// 讀取配置文件
err := viper.ReadInConfig()
if err != nil {
panic(fmt.Errorf("fatal error config file: %w", err))
}
// 獲取配置項
message := viper.GetString("message")
fmt.Println("Message:", message)
}
配置文件示例(config.toml)
message = "Hello, Viper!"
輸出
Message: Hello, Viper!
這只是一個基本的用法,但在實際項目開發中,推薦採用綁定到配置結構體的方法。
業務場景
場景一
例如,在涉及 MySQL 和 Redis 的項目中,可能需要在配置文件中設置用戶名和密碼。這時,採用結構體綁定配置的方法比較清晰,可以參考如下示例。
package main
import (
"fmt"
"github.com/spf13/viper"
"log"
)
type configStructs struct {
MySQL struct {
Username string `toml:"username"`
Password string `toml:"password"`
} `toml:"mysql"`
Redis struct {
Username string `toml:"username"`
Password string `toml:"password"`
} `toml:"redis"`
}
func main() {
// 設置配置文件名稱(不包括文件擴展名)
viper.SetConfigName("config")
// 設置配置文件類型
viper.SetConfigType("toml")
// 添加配置文件搜索路徑
viper.AddConfigPath(".")
// 讀取配置文件
err := viper.ReadInConfig()
if err != nil {
log.Fatal(fmt.Errorf("fatal error config file: %w", err))
}
// 將配置文件解析到結構體
configs := new(configStructs)
err = viper.Unmarshal(configs)
if err != nil {
log.Fatal(fmt.Errorf("fatal error config file: %w", err))
}
fmt.Println("MySQL-Username:", configs.MySQL.Username)
fmt.Println("MySQL-Password:", configs.MySQL.Password)
fmt.Println("Redis-Username:", configs.Redis.Username)
fmt.Println("Redis-Password:", configs.Redis.Password)
}
配置文件示例(config.toml)
[mysql]
username = "mysql"
password = "mysql_qwerty"
[redis]
username = "redis"
password = "redis_qwerty"
輸出:
MySQL-Username: mysql
MySQL-Password: mysql_qwerty
Redis-Username: redis
Redis-Password: redis_qwerty
場景二
例如,目標是發佈一個包含所有必需配置的獨立二進制包,而不將配置文件暴露在項目頂層目錄。我們應該如何將配置文件嵌入到二進制文件中,確保它們在運行時可以被正確訪問?
改造起來不麻煩,可參考如下示例。
package main
import (
"bytes"
_ "embed"
"fmt"
"github.com/spf13/viper"
"log"
)
type configStructs struct {
MySQL struct {
Username string `toml:"username"`
Password string `toml:"password"`
} `toml:"mysql"`
Redis struct {
Username string `toml:"username"`
Password string `toml:"password"`
} `toml:"redis"`
}
var (
//go:embed config.toml
configFile []byte
)
func main() {
// 設置配置文件名稱(不包括文件擴展名)
viper.SetConfigName("config")
// 設置配置文件類型
viper.SetConfigType("toml")
// 添加配置文件搜索路徑
viper.AddConfigPath(".")
// 讀取配置文件
err := viper.ReadConfig(bytes.NewReader(configFile))
if err != nil {
log.Fatal(fmt.Errorf("fatal error config file: %w", err))
}
// 將配置文件解析到結構體
configs := new(configStructs)
err = viper.Unmarshal(configs)
if err != nil {
log.Fatal(fmt.Errorf("fatal error config file: %w", err))
}
fmt.Println("MySQL-Username:", configs.MySQL.Username)
fmt.Println("MySQL-Password:", configs.MySQL.Password)
fmt.Println("Redis-Username:", configs.Redis.Username)
fmt.Println("Redis-Password:", configs.Redis.Password)
}
輸出:
MySQL-Username: mysql
MySQL-Password: mysql_qwerty
Redis-Username: redis
Redis-Password: redis_qwerty
代碼封裝
目前,示例代碼都是直接在 main 函數中編寫的。
爲了提高代碼的可維護性和可重用性,我們將這些配置相關的代碼封裝成一個獨立的 configs 包。
package configs
import (
"bytes"
_ "embed"
"fmt"
"github.com/spf13/viper"
"log"
)
// ConfigStructs 定義了配置文件的結構
type ConfigStructs struct {
MySQL struct {
Username string `toml:"username"`
Password string `toml:"password"`
} `toml:"mysql"`
Redis struct {
Username string `toml:"username"`
Password string `toml:"password"`
} `toml:"redis"`
}
var (
// 配置結構體的實例
config = new(ConfigStructs)
//go:embed config.toml
configFile []byte
)
func init() {
// 設置配置文件名稱(不包括文件擴展名)
viper.SetConfigName("config")
// 設置配置文件類型
viper.SetConfigType("toml")
// 添加配置文件搜索路徑
viper.AddConfigPath(".")
// 讀取配置文件
err := viper.ReadConfig(bytes.NewReader(configFile))
if err != nil {
log.Fatal(fmt.Errorf("fatal error config file: %w", err))
}
// 將配置文件解析到結構體
err = viper.Unmarshal(config)
if err != nil {
log.Fatal(fmt.Errorf("fatal error config file: %w", err))
}
}
// Get 獲取配置項
func Get() ConfigStructs {
return *config
}
使用 configs 包:
import (
"項目名稱/pkg/configs"
"fmt"
)
// 獲取配置
fmt.Println("MySQL-Username:", configs.Get().MySQL.Username)
fmt.Println("MySQL-Password:", configs.Get().MySQL.Password)
fmt.Println("Redis-Username:", configs.Get().Redis.Username)
fmt.Println("Redis-Password:", configs.Get().Redis.Password)
輸出:
MySQL-Username: mysql
MySQL-Password: mysql_qwerty
Redis-Username: redis
Redis-Password: redis_qwerty
到這,相信已經對 Viper 有了全面的瞭解,並能夠在自己的 Go 項目中靈活應用。
本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源:https://mp.weixin.qq.com/s/W62zvlzu1rmfARE_Is7zzQ