Viper 是 Go 語言中強大的配置管理庫,廣泛用于云原生和微服務開發中。它支持多種配置文件格式(如 YAML、JSON、TOML 等)、環境變量、命令行參數以及遠程配置管理。
Viper 的主要功能
1. 支持多種格式的配置文件:
? YAML、JSON、TOML、HCL、Java properties 等。
2. 讀取環境變量:
? 支持從系統環境變量加載配置。
3. 支持命令行參數:
? 可以與 pflag 或 flag 集成,讀取命令行標志。
4. 動態配置更新:
? 可以監聽文件變化,實時更新配置。
5. 遠程配置支持:
? 支持從 Consul、Etcd 等遠程配置服務加載配置。
6. 默認值設置:
? 為配置項設置默認值,在未定義時使用。
7. 嵌套配置支持:
? 支持嵌套結構的配置項。
安裝
在項目中安裝 Viper:
go get -u github.com/spf13/viper
基本使用示例
1. 讀取 YAML 配置文件
假設有一個 config.yaml 文件:
app:name: "MyApp"version: "1.0.0"
server:port: 8080host: "localhost"
使用 Viper 讀取配置:
package mainimport ("fmt""github.com/spf13/viper"
)func main() {// 設置配置文件名和路徑viper.SetConfigName("config") // 配置文件名(不包含擴展名)viper.SetConfigType("yaml") // 配置文件類型viper.AddConfigPath(".") // 配置文件路徑// 讀取配置if err := viper.ReadInConfig(); err != nil {panic(fmt.Errorf("fatal error reading config file: %w", err))}// 獲取配置值appName := viper.GetString("app.name")appVersion := viper.GetString("app.version")serverPort := viper.GetInt("server.port")serverHost := viper.GetString("server.host")fmt.Printf("App: %s v%s running on %s:%d\n", appName, appVersion, serverHost, serverPort)
}
2. 設置默認值
viper.SetDefault("app.name", "DefaultApp")
viper.SetDefault("server.port", 3000)appName := viper.GetString("app.name") // DefaultApp
serverPort := viper.GetInt("server.port") // 3000
3. 讀取環境變量
可以綁定環境變量,便于動態設置:
package mainimport ("fmt""github.com/spf13/viper"
)func main() {// 綁定環境變量viper.AutomaticEnv()// 設置別名(可選)_ = viper.BindEnv("server.port", "APP_SERVER_PORT")// 獲取環境變量的值serverPort := viper.GetInt("server.port")fmt.Printf("Server Port from ENV: %d\n", serverPort)
}
運行時設置環境變量:
export APP_SERVER_PORT=9090
go run main.go
# Output: Server Port from ENV: 9090
4. 動態監聽配置文件變化
支持熱加載配置文件的功能:
viper.WatchConfig()
viper.OnConfigChange(func(e fsnotify.Event) {fmt.Println("Config file changed:", e.Name)
})
5. 嵌套結構綁定
支持將配置綁定到結構體:
package mainimport ("fmt""github.com/spf13/viper"
)type Config struct {App struct {Name string `mapstructure:"name"`Version string `mapstructure:"version"`}Server struct {Port int `mapstructure:"port"`Host string `mapstructure:"host"`}
}func main() {viper.SetConfigFile("config.yaml")if err := viper.ReadInConfig(); err != nil {panic(fmt.Errorf("fatal error reading config file: %w", err))}var config Configif err := viper.Unmarshal(&config); err != nil {panic(fmt.Errorf("unable to decode config into struct: %w", err))}fmt.Printf("App: %s v%s running on %s:%d\n",config.App.Name, config.App.Version, config.Server.Host, config.Server.Port)
}
6. 命令行參數結合 pflag 使用
package mainimport ("fmt""github.com/spf13/pflag""github.com/spf13/viper"
)func main() {// 定義命令行標志pflag.Int("port", 8080, "Server port")pflag.Parse()// 將命令行標志綁定到 Viper_ = viper.BindPFlags(pflag.CommandLine)// 獲取值serverPort := viper.GetInt("port")fmt.Printf("Server Port: %d\n", serverPort)
}
運行時設置參數:
go run main.go --port=9090
# Output: Server Port: 9090