1. Viper库简介
Viper是一个功能强大的Go语言配置管理库,旨在简化应用程序的配置处理。它支持多种配置文件格式,并能够从多种来源读取配置,适合现代应用程序的需求。Viper使得开发者能够专注于业务逻辑,而不必过多担心配置管理的问题。
参考文档:
2. Viper的特性
- 多种配置格式支持: Viper可以读取JSON、TOML、YAML、HCL、INI、envfile和Java properties等格式的配置文件。
- 环境变量支持: Viper可以从环境变量中读取配置。
- 命令行参数: 通过与
pflag
等库结合,Viper能够处理命令行参数,并优先覆盖其他配置来源。 - 实时监控: Viper支持实时监控配置文件的变动,并能在文件变化时自动重新加载配置。
- 远程配置系统: Viper可以从远程配置系统(如etcd或Consul)读取和监控配置变化。
- 默认值设置: 可以为不同的配置选项设置默认值,以确保应用在没有提供特定配置时仍能正常运行。
- 别名系统: Viper允许为参数设置别名,以便在不破坏现有代码的情况下重命名参数。
3. Viper读取配置的优先级
Viper支持从多个数据源读取配置值,因此当同一个配置key在多个数据源有值时,Viper读取配置的优先级从高到低如下:
- set:显示使用Set函数设置值
- flag:命令行参数
- env:环境变量
- config:配置文件
- key/value store:key/value存储系统,如 etcd
- default:默认值
4. Viper读取环境变量
Viper读取环境变量,和读取配置文件中的变量,有很大不同:
- Viper的key不区分大小写,内部会统一转为小写
- 配置文件中的变量名,对应到环境变量中,全部大写
- 环境变量不方便表示层级,因此在层级key和环境变量对应时,通常把点和中划线替换为下划线
5. 安装Viper
1
| go get github.com/spf13/viper
|
6. Viper简单示例
以下是一个简单的示例,展示如何使用Viper加载YAML配置文件并从环境变量中覆盖某些值。
1、初始化一个golang项目
1 2 3
| mkdir viper-demo && cd viper-demo go mod init viper-demo go get github.com/spf13/viper
|
2、创建配置文件 config.yaml
1 2
| addr: 0.0.0.0 port: 8080
|
3、编写代码 main.go
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
| package main
import ( "fmt" "github.com/spf13/viper" )
type Config struct { Addr string Port int }
func main() { viper.SetConfigName("config") viper.SetConfigType("yaml") viper.AddConfigPath(".")
if err := viper.ReadInConfig(); err != nil { panic(fmt.Errorf("无法读取配置文件: %s", err)) }
viper.AutomaticEnv()
config := Config{ Addr: viper.GetString("addr"), Port: viper.GetInt("port"), }
fmt.Printf("地址: %s, 端口: %d\n", config.Addr, config.Port) }
|
4、运行 main.go
5、环境变量覆盖配置
1 2 3
| export ADDR=127.0.0.1
go run main.go
|
7. Viper层级配置示例
1、修改配置文件 config.yaml
1 2 3
| http: addr: 0.0.0.0 port: 8080
|
2、编写代码 main.go
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37
| package main
import ( "fmt" "strings" "github.com/spf13/viper" )
type Config struct { Addr string Port int }
func main() { viper.SetConfigName("config") viper.SetConfigType("yaml") viper.AddConfigPath(".")
if err := viper.ReadInConfig(); err != nil { panic(fmt.Errorf("无法读取配置文件: %s", err)) }
viper.AutomaticEnv() viper.SetEnvKeyReplacer(strings.NewReplacer(".", "_", "-", "_"))
config := Config{ Addr: viper.GetString("http.addr"), Port: viper.GetInt("http.port"), }
fmt.Printf("地址: %s, 端口: %d\n", config.Addr, config.Port) }
|
3、运行 main.go
4、环境变量覆盖配置
1 2
| export HTTP_ADDR=127.0.0.1 go run main.go
|
8. Viper层级配置示例进阶
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39
| package main
import ( "fmt" "strings" "github.com/spf13/viper" )
type Config struct { HTTP struct { Addr string Port int } }
func main() { viper.SetConfigName("config") viper.SetConfigType("yaml") viper.AddConfigPath(".")
if err := viper.ReadInConfig(); err != nil { panic(fmt.Errorf("无法读取配置文件: %s", err)) }
viper.AutomaticEnv() viper.SetEnvKeyReplacer(strings.NewReplacer(".", "_", "-", "_"))
var config *Config if err := viper.Unmarshal(&config); err != nil { panic(err) }
fmt.Printf("地址: %s, 端口: %d\n", config.HTTP.Addr, config.HTTP.Port) }
|