golang viper tips
December 15, 2019
简介
vipper是golang下一个配置文件的解决方案,功能强大,也被很多开源项目所引用。主要特性包括:
- setting defaults
- reading from JSON, TOML, YAML, HCL, envfile and Java properties config files
- live watching and re-reading of config files (optional)
- reading from environment variables
- reading from remote config systems (etcd or Consul), and watching changes
- reading from command line flags
- reading from buffer
- setting explicit values
具体使用方法就不copy了,主要记录下使用过程中遇到的一些小问题,避免后续再次踩坑。
如何使用
配置文件的解析、使用方法有多种,简单的方法在业务代码中直接调用viper相关的API:
- 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
这种方案简单,各个go文件中引入viper object,需要时读取。个人不太喜欢这种方式,一是太多地方引入了viper,业务跟配置解决方案耦合太高。二是个人喜欢统一对配置做些前置检查,避免无效配置。将配置相关解析的代码放在一起而非散落各地的维护性也更高。所以一般使用struct来承担解析后的结果。典型代码如下:
对应配置文件内容如下:
注意struct中的mapstructure标签,作用类似于json标签,用作控制marshal/unmarshal的过程。
另外在对一些复杂数据结构的支持上,如上面的map[int] struct也做了很好的支持,避免二次解析。
其他
如果仅从上面的内容看,viper跟json直接解析一个config.json库没啥差别。但是viper提供了更多的配置的能力。
Viper does the following for you:
- Find, load, and unmarshal a configuration file in JSON, TOML, YAML, HCL, INI, envfile or Java properties formats.
- Provide a mechanism to set default values for your different configuration options.
- Provide a mechanism to set override values for options specified through command line flags.
- Provide an alias system to easily rename parameters without breaking existing code.
- Make it easy to tell the difference between when a user has provided a command line or config file which is the same as the default.
Viper uses the following precedence order. Each item takes precedence over the item below it:
- explicit call to Set
- flag
- env
- config
- key/value store
- default
个人在项目中遇到个小问题,项目部署使用内部的容器平台,而这种容器平台使用环境变量来映射相关端口等信息。之前在配置文件自己指定端口的方法行不通了。如果之前使用了viper来获取,这个就不再是个问题了,可以通过BindEnv方法来兼容。
viper的更多高级特性有待摸索,后续项目需要实际使用时再研究。