viper 是一个配置解决方案,拥有丰富的特性:
- 支持
JSON、TOML、YAML、HCL、envfile、Java properties等多种格式的配置文件; - 可以设置监听配置文件的修改,修改时自动加载新的配置;
- 从环境变量、命令行选项和
io.Reader中读取配置; - 从远程配置系统中读取和监听修改,如
etcd/Consul; - 代码逻辑中显示设置键值。
安装 #
go get -u github.com/spf13/viper
读取配置 #
使用默认实例读取配置文件
package main
import (
"fmt"
"github.com/spf13/viper"
)
func main() {
viper.SetConfigName("config") // 设置配置文件名,不包括扩展名
viper.AddConfigPath("/etc/appname/") // 添加配置文件搜索路径
viper.AddConfigPath("$HOME/.appname") // 可以添加多个搜索路径
err := viper.ReadInConfig() // 读取配置文件
if err != nil {
panic(fmt.Errorf("Fatal error config file: %s \n", err))
}
// 使用 viper.Get 或其他类型特定方法获取配置
fmt.Println(viper.GetString("somekey"))
}
也可以构造新的实例加载配置文件
package main
import (
"fmt"
"github.com/spf13/viper"
)
func main() {
config := viper.New()
config.SetConfigName("config") // 设置配置文件名,不包括扩展名
config.AddConfigPath("/etc/appname/") // 添加配置文件搜索路径
config.AddConfigPath("$HOME/.appname") // 可以添加多个搜索路径
err := config.ReadInConfig() // 读取配置文件
if err != nil {
panic(fmt.Errorf("Fatal error config file: %s \n", err))
}
// 使用 viper.Get 或其他类型特定方法获取配置
fmt.Println(config.GetString("somekey"))
}
读取配置流 #
除了读取文件,Viper 还可以从任何实现了 io.Reader 接口的对象中读取配置。
viper.SetConfigType("yaml")
yamlExample := []byte(`
name: myapp
`)
viper.ReadConfig(bytes.NewBuffer(yamlExample))
fmt.Println(viper.Get("name"))
设置参数默认值 #
viper.SetDefault("ContentDir", "content")
viper.SetDefault("LayoutDir", "layouts")
监听配置文件变化 #
Viper 支持监听配置文件的变化,并在文件更改时触发回调函数。
viper.WatchConfig()
viper.OnConfigChange(func(e fsnotify.Event) {
fmt.Println("Config file changed:", e.Name)
})
配置参数别名 #
viper.RegisterAlias("base", "alias")
viper.Set("base", true)
fmt.Println(viper.GetBool("base")) // 输出: true
fmt.Println(viper.GetBool("alias")) // 输出: true
解序列化 #
可以选择将全部或特定值解序列化到一个结构体、映射等中。
有两种方法可以实现这一点:
Unmarshal(rawVal any) : errorUnmarshalKey(key string, rawVal any) : error
type config struct {
Port int
Name string
PathMap string `mapstructure:"path_map"`
}
var C config
err := viper.Unmarshal(&C)
if err != nil {
t.Fatalf("unable to decode into struct, %v", err)
}
写入配置文件 #
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")
常见问题 #
配置属性含下划线无法读取 #
可以添加 Tag mapstructure 以读取带下划线的参数
type MySQL struct {
DSN string `yaml:"dsn" mapstructure:"dsn"`
MaxIdleConns int `yaml:"max_idle_conns" mapstructure:"max_idle_conns"`
MaxOpenConns int `yaml:"max_open_conns" mapstructure:"max_open_conns"`
ConnMaxLifetime int `yaml:"conn_max_lifetime" mapstructure:"conn_max_lifetime"`
}