viper是一个不错的配置文件管理库, 他支持的配置文件类型依次有 "json", "toml", "yaml", "yml", "properties", "props", "prop", "hcl", "tfvars", "dotenv", "env", "ini" ; 支持的远程服务协议有 "etcd", "etcd3", "consul", "firestore", "nats"
go依赖库安装 go get github.com/spf13/viper
viper常用的使用
viper在其内部,加载后就会自动初始化一个Viper对象, 在其包内对大部分的方法都提供了对应的字节访问函数, 所以我们可以像使用函数一样使用他内部的Viper对象的方法。 如:viper.GetString("xxx")函数, 在内部他实际上是访问的Viper的方法
以下说明viper的几种常用使用方式
通过指定配置目录和文件名获取配置信息
通过指定配置文件目录, 配置文件名 即可自动加载支持的配置文件信息,在这种情况下他们的加载优先级为.json类型的配置文件优先级最高, 最低是.ini配置文件 , 如果同目录下有多个同名的不同类型配置文件,则只会加载优先级高的那一个。
当然也可以通过 viper.SetConfigType("ini") 来指定加载的配置文件类型,这样 就只会加载符合条件的 名称.ini 的配置文件。
viper.AddConfigPath("../config") // 指定配置文件目录 相对或者绝对目录
viper.SetConfigName("config") // 设置配置文件名,这样的话 在配置目录小所有支持的文件后缀都可被读取
viper.SetConfigType("ini") // 设置配置文件类型, 注意如果不指定则会尝试所有支持的文件类型
viper.ReadInConfig() // 读取已经设置的配置文件
// 获取配置信息
pa:= viper.GetString("profile.active")
log.Println(pa)
通过直接指定配置文件路径来加载配置信息
这种方式是通过 viper.SetConfigFile()函数来进行的, 注意这个函数仅仅是设置了配置文件,不会自动读取配置文件,要读取配置文件,需要手动执行 viper.ReadInConfig()读取配置文件 或者 viper.MergeInConfig() 读取并合并配置文件
// 设置配置文件名包含后缀 的相对与当前项目根目录的路径或者绝对路径
// 如 config/config.yaml 这个主要用于加载配置目录以外的配置文件
viper.SetConfigFile("config/config.yaml")
viper.MergeInConfig() // 合并当前加入的配置文件
注意:使用viper.MergeInConfig() 读取并合并配置文件后,新的配置文件中的key会覆盖旧的key的内容。
通过reader直接读取和加载配置文件信息
这种方式用于我们自己读取配置文件后通过 viper.ReadConfig(in io.Reader) 来直接加载配置文件。 这种方式给我们提供了更好的灵活性, 可以随意加载需要的配置信息。
// 读取默认的配置文件
if data, err := os.ReadFile("config/config.yaml"); err != nil {
log.Fatalf("读取默认配置文件 config/config.yaml 异常! %v", err)
} else {
viper.ReadConfig(bytes.NewReader(data)) // 直接读取配置文件信息
}
通过 viper.MergeConfigMap(cfg map[string]any) 将已有的map数据加载到配置信息中
这种方式可以让我们通过函数viper.MergeConfigMap(cfg map[string]any) 把map数据直接加载到配置信息中。 注意这个也是合并方式,新的key会覆盖旧的key
获取环境变量中的配置信息
在使用viper.AutomaticEnv() 开启自动环境变量之后, 我们就可以像读取我们配置内容一样读取环境变量中的配置信息,
viper.AutomaticEnv() // 自动环境变量 开启后可以直接使用环境变量的配置的key来作为 viper的key来获取对应的值
goroot := viper.GetString("GOROOT") // 读取GOROOT环境变量 这个只有在启用AutomaticEnv后才有效
log.Println(goroot)
paths := viper.GetStringSlice("PATH")
log.Println(paths)
通过Writexxx保存配置信息到文件
这里主要有2个函数可以保存配置信息到文件,即 viper.WriteConfig() 使用默认配置文件 和 viper.WriteConfigAs(filename string) 自定义配置文件, 另外还有 SafeWriteXxx 即他们对应的安全模式,即文件不存在时才写入。
Viper配置对象和初始化信息参考
注意这里的 New方法是在 init初始化方法里面被调用的。 表名只要我们一加载这个库 他就会被执行。
var v *Viper
type RemoteResponse struct {
Value []byte
Error error
}
func init() {
v = New()
}
type Viper struct {
// Delimiter that separates a list of keys
// used to access a nested value in one go
keyDelim string
// A set of paths to look for the config file in
configPaths []string
// The filesystem to read config from.
fs afero.Fs
// A set of remote providers to search for the configuration
remoteProviders []*defaultRemoteProvider
// Name of file to look for inside the path
configName string
configFile string
configType string
configPermissions os.FileMode
envPrefix string
// Specific commands for ini parsing
iniLoadOptions ini.LoadOptions
automaticEnvApplied bool
envKeyReplacer StringReplacer
allowEmptyEnv bool
parents []string
config map[string]any
override map[string]any
defaults map[string]any
kvstore map[string]any
pflags map[string]FlagValue
env map[string][]string
aliases map[string]string
typeByDefValue bool
onConfigChange func(fsnotify.Event)
logger *slog.Logger
// TODO: should probably be protected with a mutex
encoderRegistry *encoding.EncoderRegistry
decoderRegistry *encoding.DecoderRegistry
}
// New returns an initialized Viper instance.
func New() *Viper {
v := new(Viper)
v.keyDelim = "."
v.configName = "config"
v.configPermissions = os.FileMode(0o644)
v.fs = afero.NewOsFs()
v.config = make(map[string]any)
v.parents = []string{}
v.override = make(map[string]any)
v.defaults = make(map[string]any)
v.kvstore = make(map[string]any)
v.pflags = make(map[string]FlagValue)
v.env = make(map[string][]string)
v.aliases = make(map[string]string)
v.typeByDefValue = false
v.logger = slog.New(&discardHandler{})
v.resetEncoding()
return v
}
当然这个库的使用不止这些,还有很多的功能, 比如配置文件自动监控,即修改后配置文件自动加载等功能, 这里就不一一列举了,有需要的自己下来用用就知道了。