viper 读取配置文件
viper
项目地址 :github.com/spf13/viper
viper 是什么
- go 开发工具,主要是用于处理各种格式的配置文件,简化程序配置的读取问题
- viper 支持:
- 设置默认配置
- 支持读取 JSON TOML YAML HCL 和 Java 属性配置文件
- 监听配置文件变化,实时读取读取配置文件内容
- 读取环境变量值
- 读取远程配置系统 (etcd Consul) 和监控配置变化
- 读取命令 Flag 值
- 读取 buffer 值
- 读取确切值
安装
1 | go get github.com/fsnotify/fsnotify |
viper 的基本用法
配置文件
json 配置文件 (config.json)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16{
"port": 10666,
"mysql": {
"url": "(127.0.0.1:3306)/biezhi",
"username": "root",
"password": "123456"
},
"redis": ["127.0.0.1:6377", "127.0.0.1:6378", "127.0.0.1:6379"],
"smtp": {
"enable": true,
"addr": "mail_addr",
"username": "mail_user",
"password": "mail_password",
"to": ["xxx@gmail.com", "xxx@163.com"]
}
}yaml 配置文件 (config1.yaml)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17port: 10666
mysql:
url: "(127.0.0.1:3306)/biezhi"
username: root
password: 123456
redis:
- 127.0.0.1:6377
- 127.0.0.1:6378
- 127.0.0.1:6379
smtp:
enable: true
addr: mail_addr
username: mail_user
password: mail_password
to:
- xxx@gmail.com
- xxx@163.com
本地配置文件读取方式
- 将上述两个配置文件和下面的 main.go 放在统一目录之下,即可实现读取配置文件
1 | package main |
- 代码详解
- viper.SetConfigName (“config”) 设置配置文件名为 config, 不需要配置文件扩展名,配置文件的类型 viper 会自动根据扩展名自动匹配.
- viper.AddConfigPath (“.”) 设置配置文件搜索的目录,. 表示和当前编译好的二进制文件在同一个目录。可以添加多个配置文件目录,如在第一个目录中找到就不不继续到其他目录中查找.
- viper.ReadInConfig () 加载配置文件内容
- viper.Get*** 获取配置文件中配置项的信息
viper 的一些高级用法
- viper 设置配置项的默认值
1 | // set default config |
- 监听和重新读取配置文件
- import “github.com/fsnotify/fsnotify”
1 | viper.WatchConfig() |
从环境变量变量中读取
- 主要用到的是下面三个个方法
1 | // AutomaticEnv has Viper check ENV variables for all. |
- 简单的使用 demo 如下所示
1 | package main |
获取远程配置
使用 github.com/spf13/viper/remote 包 import _ “github.com/spf13/viper/remote”
Viper 可以从例如 etcd、Consul 的远程 Key/Value 存储系统的一个路径上,读取一个配置字符串(JSON, TOML, YAML 或 HCL 格式). 这些值优先于默认值,但会被从磁盘文件、命令行 flag、环境变量的配置所覆盖.
本人对 consul 比较熟悉,用它来做例子
代码如下
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
26package main
import (
"fmt"
"log"
"github.com/spf13/viper"
_ "github.com/spf13/viper/remote"
)
func main() {
v := viper.New()
v.AddRemoteProvider("consul", "localhost:8500", "config")
v.SetConfigType("json") // Need to explicitly set this to json
if err := v.ReadRemoteConfig(); err != nil {
log.Println(err)
return
}
fmt.Println("获取配置文件的port", v.GetInt("port"))
fmt.Println("获取配置文件的mysql.url", v.GetString(`mysql.url`))
fmt.Println("获取配置文件的mysql.username", v.GetString(`mysql.username`))
fmt.Println("获取配置文件的mysql.password", v.GetString(`mysql.password`))
fmt.Println("获取配置文件的redis", v.GetStringSlice("redis"))
fmt.Println("获取配置文件的smtp", v.GetStringMap("smtp"))
}
从 io.Reader 中读取配置信息
- 首先给大家来段例子
1 | package main |
- 这个功能日常的使用情况较少,例如这样的一个情景:
- 配置文件放在 oss 上或者 github 某个私有仓库上,viper 并没有提供直接的接口去获取,这样我们可以基于第三方托管平台的 sdk 写一套获取配置文件 bytes 的工具,将结果放入 io.Reader 中,再进行配置文件的解析。
- 上述流程感觉好像比较鸡肋,复杂了整个流程:我既然可以通过第三方的 sdk 直接拿到 bytes,为何不自己直接进行解析呢?而要借助 viper 来解析。可能有人会说,配置文件如果格式不同呢?确实,viper 的出现就是为了针对多种格式的配置文件。但是在正式的项目中,配置文件的格式一般不会变,可以自己写一套解析的工具,也就没有使用 viper 的需求了。而且对于某一种特定格式的配置文件(JSON,YAML…),Golang 已经有足够强大的包来进行解析了。
- 但是不得不承认 viper 的实现确实是很流弊的。在一般的快速开发过程中,直接使用 viper 确实可以帮助我们省去很多的麻烦,让我们集中精力针对于业务逻辑的实现。
- 个人觉得可以根据实际需求在 viper 再进行一层封装,接入一些常用的第三方平台的 sdk(github,aliyun oss…), 这样即可以读取本地配置文件,也可以读取远端的配置文件,可以通过命令行参数来实现 dev 模式和 deploy 模式的切换。