GO管理配置viper | 青训营笔记

113 阅读3分钟

Viper是适用于Go应用程序(包括Twelve-Factor App)的完整配置解决方案。它被设计用于在应用程序中工作,并且可以处理所有类型的配置需求和格式。它支持以下特性:

  • 设置默认值
  • 从JSON、TOML、YAML、HCL、envfile和Java properties格式的配置文件读取配置信息
  • 实时监控和重新读取配置文件(可选)
  • 从环境变量中读取
  • 从远程配置系统(etcd或Consul)读取并监控配置变化
  • 从命令行参数读取配置
  • 从buffer读取配置
  • 显式配置值

Viper能够为你执行下列操作:

  1. 查找、加载和反序列化JSON、TOML、YAML、HCL、envfile和Java properties格式的配置文件。
  2. 提供一种机制为你的不同配置选项设置默认值。
  3. 提供一种机制来通过命令行参数覆盖指定选项的值。
  4. 提供别名系统,以便在不破坏现有代码的情况下轻松重命名参数。
  5. 当用户提供了与默认值相同的命令行或配置文件时,可以很容易地分辨出它们之间的区别。

Viper会按照下面的优先级。每个项目的优先级都高于它下面的项目:

  • 显示调用Set设置值
  • 命令行参数(flag)
  • 环境变量
  • 配置文件
  • key/value存储
  • 默认值

把值存入Viper

建立默认值

viper.SetDefault("ContentDir", "content") viper.SetDefault("LayoutDir", "layouts") viper.SetDefault("Taxonomies", map[string]string{"tag": "tags", "category": "categories"})

读取配置文件

viper.SetConfigName("config") // 配置文件名称(无扩展名) viper.SetConfigType("yaml") // 如果配置文件的名称中没有扩展名,则需要配置此项 viper.AddConfigPath("/etc/appname/") // 查找配置文件所在的路径 viper.AddConfigPath("$HOME/.appname") // 多次调用以添加多个搜索路径 viper.AddConfigPath(".") // 还可以在工作目录中查找配置 err := viper.ReadInConfig() // 查找并读取配置文件 if err != nil { // 处理读取配置文件的错误 panic(fmt.Errorf("Fatal error config file: %s \n", err)) } } 写入配置文件

从配置文件中读取配置文件是有用的,但是有时你想要存储在运行时所做的所有修改。为此,可以使用下面一组命令,每个命令都有自己的用途:

  • WriteConfig - 将当前的viper配置写入预定义的路径并覆盖(如果存在的话)。如果没有预定义的路径,则报错。
  • SafeWriteConfig - 将当前的viper配置写入预定义的路径。如果没有预定义的路径,则报错。如果存在,将不会覆盖当前的配置文件。
  • WriteConfigAs - 将当前的viper配置写入给定的文件路径。将覆盖给定的文件(如果它存在的话)。
  • SafeWriteConfigAs - 将当前的viper配置写入给定的文件路径。不会覆盖给定的文件(如果它存在的话)。

根据经验,标记为safe的所有方法都不会覆盖任何文件,而是直接创建(如果不存在),而默认行为是创建或截断。

监控并重新读取配置文件

viper.WatchConfig() viper.OnConfigChange(func(e fsnotify.Event) { // 配置文件发生变更之后会调用的回调函数 fmt.Println("Config file changed:", e.Name) })

从io.Reader读取配置

覆盖设置

实例

package main import ( "fmt" "github.com/gin-gonic/gin" "github.com/spf13/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) } }

从Viper获取值

在Viper中,有几种方法可以根据值的类型获取值。存在以下功能和方法:

  • 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{}

需要认识到的一件重要事情是,每一个Get方法在找不到值的时候都会返回零值。为了检查给定的键是否存在,提供了IsSet()方法。