Go 学习笔记(82)— Go 第三方库之 viper(解析配置文件、热更新配置文件)
2021/12/7 23:18:17
本文主要是介绍Go 学习笔记(82)— Go 第三方库之 viper(解析配置文件、热更新配置文件),对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
1. viper 特点
viper
是一个完整的 Go
应用程序的配置解决方案,它被设计为在应用程序中工作,并能处理所有类型的配置需求和格式。支持特性功能如下:
- 设置默认值
- 读取
JSON
、TOML
、YAML
、HCL
、envfile
和Java
属性的配置文件 - 监控配置文件改动,并热加载配置文件
- 从环境变量中读取
- 从远程配置中心读取配置(etcd/consul),并监控变动
- 从命令行标志中读取
- 从缓冲区读取
- 支持直接设置配置项的值
viper
读取配置文件的优先级顺序:
viper.Set()
所设置的值- 命令行
flag
- 环境变量
- 配置文件
- 配置中心
etcd/consul
- 默认值
注意:
viper
的配置键是不区分大小写的。
2. 安装
官网地址:https://github.com/spf13/viper 安装命令
go get github.com/spf13/viper
3. 将配置注册到 viper
3.1 创建默认值
viper.SetDefault("Name", "wohu") viper.SetDefault("Gender", "male") viper.SetDefault("City", map[string]string{"country": "China", "Province": "Beijing"})
3.2 从配置文件读取值
viper
默认不配置文件的搜索路径,将配置文件路径的搜索决定权放在用户程序中。
viper.SetConfigName("config") // 配置文件名字,注意没有扩展名 viper.SetConfigType("yaml") // 如果配置文件的名称中没有包含扩展名,那么该字段是必需的 viper.AddConfigPath("/etc/appname/") // 配置文件的路径 viper.AddConfigPath("$HOME/.appname") // 多次调用添加多个配置文件的路径 viper.AddConfigPath(".") // 在当前工作目录寻找配置文件 err := viper.ReadInConfig() // 查找并读取配置文件 if err != nil { panic(fmt.Errorf("Fatal error config file: %w \n", err)) }
3.3 将 viper值保存到配置文件
viper.WriteConfig()
将当前的配置写到预先通过 viper.AddConfigPath()
和 viper.SetConfigName()
配置的路径,如果该目录下已经有对应的配置文件则会覆盖,如果找不到对应的路径则报错。
viper.SafeWriteConfig() // 与第一个区别是不会覆盖当前已经存在的文件 viper.WriteConfigAs("/path/to/my/.config") // 会覆盖当前已经存在的文件 viper.SafeWriteConfigAs("/path/to/my/.config") // 不会覆盖当前已经存在的文件 viper.SafeWriteConfigAs("/path/to/my/.other_config")
3.4 监测并热加载配置文件
viper
支持应用程序在运行中实时读取配置文件的能力。确保在调用 WatchConfig()
之前添加所有的configPaths
。
viper.OnConfigChange(func(e fsnotify.Event) { fmt.Println("Config file changed:", e.Name) }) viper.WatchConfig()
3.5 从 io.Reader 读取配置
viper.SetConfigType("yaml") // or viper.SetConfigType("YAML") // any approach to require this configuration into your program. var yamlExample = []byte(` Hacker: true name: steve hobbies: - skateboarding - snowboarding - go clothing: jacket: leather trousers: denim age: 35 eyes : brown beard: true `) viper.ReadConfig(bytes.NewBuffer(yamlExample)) viper.Get("name") // this would be "steve"
4. 从 viper 读取配置
4.1 读取单个值方法
在 viper
中,有几种方法来获取一个值,这取决于该值的类型。存在以下函数和方法。
Get(key string) : interface{} GetBool(key string) : bool GetFloat64(key string) : float64 GetInt(key string) : int GetIntSlice(key string) : []int GetString(key string) : string GetStringMap(key string) : map[string]interface{} GetStringMapString(key string) : map[string]string GetStringSlice(key string) : []string GetTime(key string) : time.Time GetDuration(key string) : time.Duration IsSet(key string) : bool AllSettings() : map[string]interface{}
注意:如果没有找到,每个
Get
函数将返回一个0
值。为了检查一个给定的键是否存在,已经提供了IsSet()
方法。
4.1 读取嵌套的配置
{ "host": { "address": "localhost", "port": 5799 }, "datastore": { "metric": { "host": "127.0.0.1", "port": 3099 }, "warehouse": { "host": "198.0.0.1", "port": 2112 } } }
viper
可以通过传递一个以 .
为界的键值路径来访问一个嵌套字段。
GetString("datastore.metric.host") // (returns "127.0.0.1")
viper
可以通过使用路径中的数字来访问数组索引,例如
{ "host": { "address": "localhost", "ports": [ 5799, 6029 ] }, "datastore": { "metric": { "host": "127.0.0.1", "port": 3099 }, "warehouse": { "host": "198.0.0.1", "port": 2112 } } } GetInt("host.ports.1") // returns 6029
如果存在一个与划定的键路径相匹配的键,其值将被返回。例如。
{ "datastore.metric.host": "0.0.0.0", "host": { "address": "localhost", "port": 5799 }, "datastore": { "metric": { "host": "127.0.0.1", "port": 3099 }, "warehouse": { "host": "198.0.0.1", "port": 2112 } } } GetString("datastore.metric.host") // returns "0.0.0.0"
5. 使用示例
代码结构如下:
. ├── conf │ └── config.yaml ├── config │ └── config.go ├── go.mod ├── go.sum ├── main.go └── README.md 2 directories, 6 files
config.yaml
内容
name: demo host: 127.0.0.1:3306 username: root password: root
config.go
内容:
package config import ( "log" "github.com/fsnotify/fsnotify" "github.com/spf13/viper" ) type Config struct { Name string Host string Username string Password string } func Init() (*Config, error) { viper.AddConfigPath("conf") // 设置配置文件路径 viper.SetConfigName("config") // 设置配置文件名 viper.SetConfigType("yaml") // 设置配置文件类型格式为YAML // 初始化配置文件 if err := viper.ReadInConfig(); err != nil { // viper解析配置文件 return &Config{}, err } // 监控配置文件变化并热加载程序,即不重启程序进程就可以加载最新的配置 viper.WatchConfig() viper.OnConfigChange(func(e fsnotify.Event) { log.Printf("Config file changed: %s", e.Name) }) c := &Config{ Name: viper.GetString("name"), Host: viper.GetString("host"), Username: viper.GetString("username"), Password: viper.GetString("password"), } return c, nil }
main.go
内容:
package main import ( "fmt" "time" "webserver/config" "github.com/spf13/viper" ) func main() { // init config _, err := config.Init() if err != nil { fmt.Println(err) } // 注意:只能在 init 之后再次通过 viper.Get 方法读取配置,否则不生效 for { cfg := &config.Config{ Name: viper.GetString("name"), Host: viper.GetString("host"), Username: viper.GetString("username"), Password: viper.GetString("password"), } fmt.Println(cfg.Name) time.Sleep(4 * time.Second) } }
运行 main.go
之后修改配置文件查看打印:
$ go run main.go 123 123 2021/12/03 14:05:45 Config file changed: /home/wohu/goProject/webserver/conf/config.yaml 2021/12/03 14:05:45 Config file changed: /home/wohu/goProject/webserver/conf/config.yaml 345 345 345 2021/12/03 14:05:56 Config file changed: /home/wohu/goProject/webserver/conf/config.yaml 2021/12/03 14:05:56 Config file changed: /home/wohu/goProject/webserver/conf/config.yaml demo demo
这篇关于Go 学习笔记(82)— Go 第三方库之 viper(解析配置文件、热更新配置文件)的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-12-24MongoDB资料:新手入门完全指南
- 2024-12-20go-zero 框架的 RPC 服务 启动start和停止 底层是怎么实现的?-icode9专业技术文章分享
- 2024-12-19Go-Zero 框架的 RPC 服务启动和停止的基本机制和过程是怎么实现的?-icode9专业技术文章分享
- 2024-12-18怎么在golang中使用gRPC测试mock数据?-icode9专业技术文章分享
- 2024-12-15掌握PageRank算法核心!你离Google优化高手只差一步!
- 2024-12-15GORM 中的标签 gorm:"index"是什么?-icode9专业技术文章分享
- 2024-12-11怎么在 Go 语言中获取 Open vSwitch (OVS) 的桥接信息(Bridge)?-icode9专业技术文章分享
- 2024-12-11怎么用Go 语言的库来与 Open vSwitch 进行交互?-icode9专业技术文章分享
- 2024-12-11怎么在 go-zero 项目中发送阿里云短信?-icode9专业技术文章分享
- 2024-12-11怎么使用阿里云 Go SDK (alibaba-cloud-sdk-go) 发送短信?-icode9专业技术文章分享