1.介绍
Viper是一个配置管理库,支持多种格式的配置文件,并且可以从环境变量、命令行参数等读取配置。
1.下载viper
go get github.com/spf13/viper
2.基本使用
1.使用程序代码设置并且读取配置
- 后面的会覆盖前面的设置, 但是不同的设置方式有一些优先级区别.
Get函数如果找不到相应的配置,都将返回零值。要检查给定的 key 是否存在,使用IsSet()方法.
func WriteBasicUse() {
viper.SetDefault("ip", "192.168.80.51")
viper.Set("port", 10086)
ip := viper.GetString("ip")
port := viper.GetInt("port")
fmt.Println("配置Ip是:", ip)
fmt.Println("配置端口是:", port)
// 会覆盖设置的192.168.80.51
viper.SetDefault("ip", "192.168.80.59")
fmt.Println("重新配置Ip是:", viper.GetString("ip"))
// 不会覆盖,因为Set的优先级最高
viper.SetDefault("port", 9999)
fmt.Println("重新配置端口是:", viper.GetInt("port"))
}
2.优先级配置
对相同的配置key, 使用不同的api进行赋值设置, 会存在优先级问题,主要有下面几个
-
显式调用 Set() 方法(最高优先级)
-
命令行标志(Flags)(注意:必须启动时带了命令参数)
-
环境变量
-
配置文件
-
默认值(最低优先级)
func UsePriority(){
// 设置
viper.SetDefault("ip", "192.168.80.59")
var key string
pflag.StringVar(&ip, "ip", "", "程序运行的ip")
pflag.Parse()
viper.BindPFlags(pflag.CommandLine)
// 输出命令行设置ip ,因为优先级高
fmt.Println("配置ip是:", viper.GetString("ip"))
}
// 运行命令 go run main.go 读取配置为192.168.80.59
// 运行命令 go run main.go --ip="127.0.0.1" 读取配置为127.0.0.1
3.将配置写到文件中
可以写入json yaml toml 类型文件
//定义结构体
type Cfg struct {
Addr string
No string
}
func WriteConfigFile() {
// 设置结构体配置
viper.Set("info", Cfg{Addr: "湖北武汉", No: 1})
// 单独设置一个名字
viper.Set("name", "sa")
// 设置配置类型
viper.SetConfigType("json")
// 写入json格式,文件存在就不写入
err := viper.SafeWriteConfigAs("config.json")
if err != nil {
fmt.Println("写入json配置错误", err)
} else {
fmt.Println("写入json配置成功")
}
viper.SetConfigType("yaml")
// 文件yaml存在就不写入
yamlErr := viper.SafeWriteConfigAs("config.yaml")
if yamlErr != nil {
fmt.Println("写入yaml配置错误", yamlErr)
} else {
fmt.Println("写入yaml配置成功")
}
viper.SetConfigType("toml")
// 文件toml存在就不写入
tomlErr := viper.SafeWriteConfigAs("config.toml")
if tomlErr != nil {
fmt.Println("写入tomlErr配置错误", tomlErr)
} else {
fmt.Println("写入toml配置成功")
}
}
{
"info": {
"Addr": "湖北武汉",
"No": 1
},
"name": "sa"
}
info:
addr: 湖北武汉
"no": 1
name: sa
4.读取配置文件中的配置
思路:先设置配置类型,再设置具体文件
func ReadConfigFile() {
// 设置类型 指定文件
viper.SetConfigType("json")
viper.SetConfigFile("config.json")
readErr := viper.ReadInConfig()
if readErr != nil {
fmt.Println("读取配置文件失败", readErr)
return
}
info := viper.Get("info")
name := viper.Get("name")
fmt.Println("读取内容为", info)
fmt.Println("读取内容为", name)
}
5.监听配置文件变化
func MonitorConfigFile() {
// 先读取旧的值
ov := viper.New()
ov.SetConfigType("json")
ov.SetConfigFile("config.json")
ov.ReadInConfig()
// 解析配置
var config Cfg{}
if err := viper.Unmarshal(&config); err != nil {
panic("Failed to unmarshal config: " + err.Error())
}
// 设置类型 指定文件
viper.SetConfigType("json")
viper.SetConfigFile("config.json")
viper.WatchConfig()
viper.OnConfigChange(func(e fsnotify.Event) {
fmt.Println("配置文件发生变更", e.Name, e.Op)
fmt.Println("配置文件发生变更前的值是:", ov.Get("info"))
fmt.Println("配置文件发生变更后的值是:", viper.Get("info"))
})
fmt.Println("正在监听....")
// time.After(5*time.Second)//5秒退出
// for {
// } //使用for阻塞
select {}
}
6.读取环境变量
func ReadEnvVar() {
viper.AutomaticEnv()
// 读取全部
viper.SetEnvPrefix("")
ACSvcPort := viper.Get("ACSvcPort")
USERNAME := viper.Get("USERNAME")
fmt.Println("读取到系统环境变量为:", ACSvcPort, USERNAME)
viper.SetEnvPrefix("ENV")
fmt.Println(viper.Get("version"))
}
7.读取命令行
func ReadCmdLine() {
var ip string
var port int
// pflag 等于前面加-- go run main.go --ip 192.168.0.1 --port 5020
// go run main.go -h 查看所有参数
pflag.StringVar(&ip, "ip", "", "程序运行的ip")
pflag.IntVar(&port, "port", 0, "程序运行的端口")
pflag.Parse()
viper.BindPFlags(pflag.CommandLine)
fmt.Println("程序运行读取ip为", viper.Get("ip"))
fmt.Println("程序运行读取端口为", viper.Get("port"))
}
浙公网安备 33010602011771号