经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » 程序设计 » Go语言 » 查看文章
Viper:强大的Go配置解析库 - Hello-Brand
来源:cnblogs  作者:Hello-Brand  时间:2024/8/20 8:58:55  对本文有异议

1 介绍

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

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

2 Golang项目中的使用

2.1 在go中安装Viper

  1. # 终端中输入如下命令
  2. 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,里面可以放一些基本的、通用的配置信息。

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

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

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

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

  1. white_list:
  2. user_id: # 用户列表
  3. - 063105015
  4. - 063105024
  5. - 063105028
  6. request_path: # 访问路径
  7. - /api/v1/users
  8. - /api/v1/ops

2.4 配置映射的结构体

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

2.4.1 config.go

  1. package config
  2. // 配置文件解析汇总
  3. type Configuration struct {
  4. App App `mapstructure:"app" json:"app" yaml:"app"`
  5. MYSQL MYSQL `mapstructure:"mysql" json:"mysql" yaml:"mysql"`
  6. }
  7. // 配置文件解析:app
  8. type App struct {
  9. Env string `mapstructure:"env" json:"env" yaml:"env"`
  10. Port string `mapstructure:"port" json:"port" yaml:"port"`
  11. AppName string `mapstructure:"app_name" json:"app_name" yaml:"app_name"`
  12. AppUrl string `mapstructure:"app_url" json:"app_url" yaml:"app_url"`
  13. }
  14. // 配置文件解析:mysql
  15. type MYSQL struct {
  16. Host string `mapstructure:"host" json:"host" yaml:"host"`
  17. Port string `mapstructure:"poet" json:"port" yaml:"port"`
  18. User string `mapstructure:"user" json:"user" yaml:"user"`
  19. Password string `mapstructure:"password" json:"password" yaml:"password"`
  20. DbName string `mapstructure:"db_name" json:"db_name" yaml:"db_name"`
  21. }

2.4.2 custom.go

  1. package config
  2. type Custom struct {
  3. WhiteList whiteList `mapstructure:"white_list" json:"white_list" yaml:"white_list"`
  4. }
  5. // 配置文件解析汇总
  6. type whiteList struct {
  7. UserId []string `mapstructure:"user_id" json:"user_id" yaml:"user_id"`
  8. RequestPath []string `mapstructure:"request_path" json:"request_path" yaml:"request_path"`
  9. }

2.5 创建Global全局变量解析

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

  1. package global
  2. import (
  3. "github.com/spf13/viper"
  4. config "traffic.demo/config/model"
  5. )
  6. // 定义一个全局的Application
  7. type Application struct {
  8. ConfigViper *viper.Viper
  9. Config config.Configuration
  10. Custom config.Custom
  11. }
  12. // 初始化Application
  13. var App = new(Application)

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

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

  1. package bootstrap
  2. import (
  3. "fmt"
  4. "github.com/fsnotify/fsnotify"
  5. "github.com/spf13/viper"
  6. "traffic.demo/global"
  7. )
  8. // configAssemble 是一个泛型函数,用于组装配置文件并返回 viper.Viper 指针
  9. //
  10. // 参数:
  11. //
  12. // configPath string - 配置文件路径
  13. // viperStruct T - 用来接收配置文件的结构体
  14. //
  15. // 返回值:
  16. //
  17. // *viper.Viper - viper.Viper 指针
  18. func configAssemble[T any](configPath string, viperStruct T) *viper.Viper {
  19. // 初始化 viper
  20. v := viper.New()
  21. // 配置文件地址
  22. v.SetConfigFile(configPath)
  23. // 配置文件类型,yaml
  24. v.SetConfigType("yaml")
  25. if err := v.ReadInConfig(); err != nil {
  26. panic(fmt.Errorf("read config failed: %s \n", err))
  27. }
  28. // 监听配置文件
  29. v.WatchConfig()
  30. v.OnConfigChange(func(in fsnotify.Event) {
  31. fmt.Println("config file changed:", in.Name)
  32. // 重载配置 &global.App.Config
  33. if err := v.Unmarshal(viperStruct); err != nil {
  34. fmt.Println(err)
  35. }
  36. })
  37. // 将配置赋值给全局变量 &global.App.Config
  38. if err := v.Unmarshal(viperStruct); err != nil {
  39. fmt.Println(err)
  40. }
  41. return v
  42. }
  43. // InitializeConfig 初始化配置函数
  44. func InitializeConfig() {
  45. // 全局应用文件配置路径,这边是我们的具体global config文件地址
  46. config := "conf/files/config.yaml"
  47. configAssemble(config, &global.App.Config)
  48. // 用户自定义的配置(根据不同的运行环境,加载不同的配置文件)
  49. customConfig := fmt.Sprintf("%s%s%s", "conf/files/", global.App.Config.App.Env, "/custom.yaml")
  50. configAssemble(customConfig, &global.App.Custom)
  51. }

2.6 整体文件结构如下

image

2.7 运行结果

main.go 代码如下:

  1. package main
  2. import (
  3. "fmt"
  4. "traffic.demo/global"
  5. )
  6. // main 函数是程序的入口点
  7. func main() {
  8. bootstrap.InitializeConfig()
  9. fmt.Println("Traffic Service Started...!")
  10. var globalCong = global.App.Config
  11. fmt.Printf("globalCong: %+v\n", globalCong)
  12. var customCong = global.App.Custom
  13. fmt.Printf("customCong: %+v\n", customCong)
  14. }

效果如下:
image

3 总结

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

原文链接:https://www.cnblogs.com/wzh2010/p/18364344

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号