Viper:强大的Go配置解析库

1 介绍

Viper是适用于Go应用程序的完整配置解决方案。它被设计用于在应用程序中工作,并且可以处理所有类型的配置需求和格式。目前Star 26.6k, 它支持以下特性:

  • 设置默认值
  • 从JSON、TOML、YAML、HCL、envfile和Java properties格式的配置文件读取配置信息
  • 实时监控和重新读取配置文件(可选)
  • 从环境变量中读取
  • 从远程配置系统(etcd或Consul)读取并监控配置变化
  • 从命令行参数读取配置
  • 从buffer读取配置
  • 显式配置值

2 Golang项目中的使用

2.1 在go中安装Viper

# 终端中输入如下命令 ArchitePlus@MacBook-Air traffic.demo % go get github.com/spf13/viper 

2.2 编写通用配置文件

因为能支持多重配置文件格式,包含 JSON、TOML、YAML、HCL、INI、envfile 和 Java 属性文件,方便开发者根据项目需求选择合适的格式。
我们这边使用yaml做示例。

创建一个conf文件夹,添加子文件夹files,然后在下面添加config.yaml,里面可以放一些基本的、通用的配置信息。

app: # 应用基本配置   env: local # 环境名称   port: 8888 # 服务监听端口号   app_name: traffic-demo # 应用名称   app_url: http://localhost # 应用访问地址   MySQL: # MySQL配置   host: 127.0.0.1 # MySQL主机地址   port: 3306 # MySQL端口号   user: root # MySQL用户名   password: <PASSWORD>    db_name: traffic # MySQL数据库名 

可以看到,我们有两个配置信息,一个是 app,一个是MySQL。

2.3 编写用户自定义配置文件

还有一些用户自定义的配置文件(可能有多个), 是需要根据不同的运行环境(local、dev、beta、prod)来进行区分的.所以我们在config/files/下面创建四个文件夹 localdevbetaprod 四个文件夹,每个文件夹都有一个custom.yaml文件,当 app.env 的值变化的时候,读取的文件也跟着变化,下面是local的信息

white_list:    user_id: # 用户列表   - 063105015   - 063105024   - 063105028   request_path: # 访问路径   - /api/v1/users   - /api/v1/ops 

2.4 配置映射的结构体

我们需要配置结构体(实体对象)来映射这俩配置,这样的话,后面在调用的时候非常方便。
conf文件夹下面添加子文件夹model,存放解析映射的结构体,这边新增一个config.go和一个custom.go文件,内容如下:

2.4.1 config.go

package config  // 配置文件解析汇总 type Configuration struct { 	App   App   `mapstructure:"app" json:"app" yaml:"app"` 	MYSQL MYSQL `mapstructure:"mysql" json:"mysql" yaml:"mysql"` }  // 配置文件解析:app type App struct { 	Env     string `mapstructure:"env" json:"env" yaml:"env"` 	Port    string `mapstructure:"port" json:"port" yaml:"port"` 	AppName string `mapstructure:"app_name" json:"app_name" yaml:"app_name"` 	AppUrl  string `mapstructure:"app_url" json:"app_url" yaml:"app_url"` }  // 配置文件解析:mysql type MYSQL struct { 	Host     string `mapstructure:"host" json:"host" yaml:"host"` 	Port     string `mapstructure:"poet" json:"port" yaml:"port"` 	User     string `mapstructure:"user" json:"user" yaml:"user"` 	Password string `mapstructure:"password" json:"password" yaml:"password"` 	DbName   string `mapstructure:"db_name" json:"db_name" yaml:"db_name"` }  

2.4.2 custom.go

package config  type Custom struct { 	WhiteList whiteList `mapstructure:"white_list" json:"white_list" yaml:"white_list"` }  // 配置文件解析汇总 type whiteList struct { 	UserId      []string `mapstructure:"user_id" json:"user_id" yaml:"user_id"` 	RequestPath []string `mapstructure:"request_path" json:"request_path" yaml:"request_path"` }  

2.5 创建Global全局变量解析

新建一个 global/app.go 文件,定义 Application 结构体,用来存放一些项目启动时的变量,方便调用。
目前先将 viper 结构体和 Configuration 结构体放入,后续会陆续添加其他配置信息。

package global  import ( 	"github.com/spf13/viper" 	config "traffic.demo/config/model" )  // 定义一个全局的Application type Application struct { 	ConfigViper *viper.Viper 	Config      config.Configuration 	Custom      config.Custom }  // 初始化Application var App = new(Application)  

2.5 关键步骤:结构体映射逻辑

配置文件要映射到结构体,这样才能把配置数据提取出来,这边创建 bootstrap/config.go 文件,作为核心解析代码的载体,代码如下(代码中的解释已经很清楚了):

package bootstrap  import ( 	"fmt"  	"github.com/fsnotify/fsnotify" 	"github.com/spf13/viper" 	"traffic.demo/global" )  // configAssemble 是一个泛型函数,用于组装配置文件并返回 viper.Viper 指针 // // 参数: // //	configPath string - 配置文件路径 //	viperStruct T - 用来接收配置文件的结构体 // // 返回值: // //	*viper.Viper - viper.Viper 指针 func configAssemble[T any](configPath string, viperStruct T) *viper.Viper { 	// 初始化 viper 	v := viper.New() 	// 配置文件地址 	v.SetConfigFile(configPath) 	// 配置文件类型,yaml 	v.SetConfigType("yaml") 	if err := v.ReadInConfig(); err != nil { 		panic(fmt.Errorf("read config failed: %s n", err)) 	}  	// 监听配置文件 	v.WatchConfig() 	v.OnConfigChange(func(in fsnotify.Event) { 		fmt.Println("config file changed:", in.Name) 		// 重载配置 &global.App.Config 		if err := v.Unmarshal(viperStruct); err != nil { 			fmt.Println(err) 		} 	}) 	// 将配置赋值给全局变量 &global.App.Config 	if err := v.Unmarshal(viperStruct); err != nil { 		fmt.Println(err) 	}  	return v }  // InitializeConfig 初始化配置函数 func InitializeConfig() { 	// 全局应用文件配置路径,这边是我们的具体global config文件地址 	config := "conf/files/config.yaml" 	configAssemble(config, &global.App.Config)  	// 用户自定义的配置(根据不同的运行环境,加载不同的配置文件) 	customConfig := fmt.Sprintf("%s%s%s", "conf/files/", global.App.Config.App.Env, "/custom.yaml") 	configAssemble(customConfig, &global.App.Custom)  } 

2.6 整体文件结构如下

Viper:强大的Go配置解析库

2.7 运行结果

main.go 代码如下:

package main  import ( 	"fmt" 	"traffic.demo/global" )  // main 函数是程序的入口点 func main() {      bootstrap.InitializeConfig()     fmt.Println("Traffic Service Started...!")  	var globalCong = global.App.Config 	fmt.Printf("globalCong: %+vn", globalCong) 	var customCong = global.App.Custom 	fmt.Printf("customCong: %+vn", customCong) }  

效果如下:
Viper:强大的Go配置解析库

3 总结

Viper 是一个功能强大、简洁、易于的 Go 配置库,帮助开发者轻松管理应用程序的配置,并提供灵活的接入方式

发表评论

评论已关闭。

相关文章