
viper配置文件解析
1.配置文件解析
- go-ini
viper
配置两种方法:
- 直接通过viper取
- 定义全局变量,读取完配置反序列化到变量中,其他模块通过全局变量获取配置信息
WatchConfig发生变化后需要手动的再把更新后的配置给赋值给全局变量
如果使用嵌套的结构体要使用专用的mapstructuretag
应用:
viper+consul实现配置热更新。
2.基本使用
1.viper示例
func main() { viper.SetConfigName("config") // 指定配置文件名称(不需要带后缀) viper.SetConfigType("yaml") // 指定配置文件类型 viper.AddConfigPath("./conf/") // 指定查找配置文件的路径(这里使用相对路径) err := viper.ReadInConfig() // 读取配置信息 if err != nil { // 读取配置信息失败 panic(fmt.Errorf("Fatal error config file: %s \n", err)) } r := gin.Default() if err := r.Run(fmt.Sprintf(":%d", viper.Get("port"))); err != nil { panic(err) } }2.设置默认值
viper.SetDefault("ContentDir", "content") viper.SetDefault("LayoutDir", "layouts") viper.SetDefault("Taxonomies", map[string]string{"tag": "tags", "category": "categories"})3.监控并重新读取配置文件
viper.WatchConfig() viper.OnConfigChange(func(e fsnotify.Event) { // 配置文件发生变更之后会调用的回调函数 fmt.Println("Config file changed:", e.Name) })4.读取环境变量
viper.SetEnvPrefix("GIN") viper.AutomaticEnv() // 环境变量中GIN开头的 viper.BindEnv("mode") // GIN_MODE5.从命令行flag参数读取
package main import ( "flag" "github.com/spf13/pflag" ) func main() { // 使用标准库 "flag" 包 flag.Int("flagname", 1234, "help message for flagname") pflag.CommandLine.AddGoFlagSet(flag.CommandLine) pflag.Parse() viper.BindPFlags(pflag.CommandLine) i := viper.GetInt("flagname") // 从 viper 检索值 ... }6.从远程配置仓库读取
etcd
viper.AddRemoteProvider("etcd", "http://127.0.0.1:4001", "/config/hugo.json") viper.SetConfigType("json") // 因为在字节流中没有文件扩展名,所以这里需要设置下类型。支持的扩展名有 "json", "toml", "yaml", "yml", "properties", "props", "prop", "env","dotenv" err := viper.ReadRemoteConfig()consule
viper.AddRemoteProvider("consul", "localhost:8500", "MY_CONSUL_KEY") viper.SetConfigType("json") // 需要显示设置成json err := viper.ReadRemoteConfig() fmt.Println(viper.Get("port")) // 8080 fmt.Println(viper.Get("hostname")) // liwenzhou.co
3.从Viper获取值
获取值方法
获取值使用以下方法,注意 Get 返回的是空接口类型的值,后续需要根据实际情况做类型转换
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{}1.获取嵌套的键
{ "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") // (返回 "127.0.0.1")2.获取配置子树
app: cache1: max-items: 100 item-size: 64 cache2: max-items: 200 item-size: 80获取上面配置文件中 cache2 子树的配置:
viper.Sub("app.cache1")3.反序列化
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中的配置写入配置文件
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")
