一个计算机技术爱好者与学习者

0%

好好学Golang:Viper库

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

1
go run main.go

5、环境变量覆盖配置

1
2
3
export ADDR=127.0.0.1 
# 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()
// 匹配环境变量时,将配置Key中的点号(.)和横杠(-)替换为下划线(_)
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

1
go run 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() // 启用环境变量支持
// 匹配环境变量时,将配置Key中的点号(.)和横杠(-)替换为下划线(_)
viper.SetEnvKeyReplacer(strings.NewReplacer(".", "_", "-", "_"))

// 将配置文件反序列化为 config 对象
var config *Config
if err := viper.Unmarshal(&config); err != nil {
panic(err)
}

fmt.Printf("地址: %s, 端口: %d\n", config.HTTP.Addr, config.HTTP.Port)
}
  • 本文作者: 好好学习的郝
  • 原文链接: https://www.voidking.com/dev-golang-viper/
  • 版权声明: 本文采用 BY-NC-SA 许可协议,转载请注明出处!源站会即时更新知识点并修正错误,欢迎访问~
  • 微信公众号同步更新,欢迎关注~