最近这段时间在用GoLang写项目。其中如何读取配置文件一度是让我比较头疼的事情,好在最后都解决了,这里简单记录一下GoLang读取配置文件的方式。
因为写了多年java springboot项目的缘故,在多种配置方式中独独比较偏爱yaml的格式。因此为新项目选择配置文件的时候就毫不犹豫地选择了继续使用yaml。
使用yaml时遇到了这样几个问题:
- yaml配置文件读取并映射为struct
- yaml多配置文件读取
- 适应性选择配置
接下来就以这几个问题的顺序来简单介绍下使用GoLang如何读取yaml配置文件以及关于配置文件选择的问题。
读取yaml配置文件
也许很多人都在网上搜索过“golang读取yaml”这样的词条,搜索结果也通常大部分都是推荐使用gopkg.in/yaml
这个package。
gopkg.in/yaml
诚然是读取yaml最经典的一个方案,但却不是最简单易用的一个方案。
读取yaml(或其它类型的配置文件)我首先推荐使用viper,因为它用起来最简洁。
来看一个viper读取配置文件的示例:
1 2 3 4 |
viper.AddConfigFile(path_config_file) if err := viper.ReadConfig(); nil != err { log.Fatalf("配置文件读取失败: %v\n", err) } |
到这里配置文件的读取就已经完成了。
使用配置信息时可以使用viper的GetInt
、GetString
、GetBool
等方法来读取。
比如类似下面的配置信息:
1 2 3 4 5 6 7 8 |
# # config worker1: # worker robin name: robin age: 26 worker2: # worker tom name: tom age: 32 |
要获取配置中的age信息时可以这样做:
1 |
age := viper.GetInt("worker1.age") |
viper也支持将配置信息渲染为struct对象:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
//Workshop 作坊 type Workshop struct { W1 Worker `mapstructure:"worker1"` W2 Worker `mapstructure:"worker2"` } //Worker 工人 type Worker struct { Name string Age int64 } var W = new(Workshop) if err := viper.Unmarshal(W); nil != err { log.Fatalf("赋值配置对象失败,异常信息:%v", err) } |
需要注意一点:viper并不是直接将yaml配置文本转换成了struct对象。viper是先将配置信息转换成了map结构,而后再通过github.com/mitchellh/mapstructure
这个模块将map对象转换为struct对象。因此在配置struct成员映射关系时使用的是mapstructure关键字,而非yaml关键字。
yaml多配置文件读取
在java springboot中可以做这样的配置:在application.yml做通用的配置;在application-dev.yml和application-prod.yml添加适应不同环境的个性化配置;如有相同配置项,后者可以覆盖前者。
我非常喜欢这种配置方法,能够灵活适配不同环境,减少冗余配置。但很不幸,viper目前并不支持类似的操作。头疼了一段时间后,干脆参考viper的代码写了一个新的项目vibe。这个项目目前的版本是0.0.5。在读取yaml文件这一点上,vibe的使用方式和viper几乎是一样的——除了能够满足读取多配置文件这一项。
看下示例代码:
1 2 3 4 5 6 7 8 |
vibe.AddConfigFiles("conf/config.yml", "conf/config-dev.yml") if err := vibe.ReadConfig(); nil != err { log.Fatalf("读取配置文件失败,异常信息:%v", err) } if err := vibe.Unmarshal(W); nil != err { log.Fatalf("赋值配置对象失败,异常信息:%v", err) } |
这里只看第一行代码就好。这行代码里读取了两个配置文件:config.yml和config-dev.yml,两个文件中的配置有重合之处(不详细贴配置信息了,可参考后文示例代码),但是最终输出信息以后者中的配置为准。
适应性选择配置
虽然这个写在最后,不过应该是最好解决的事情了,通过环境变量、命令参数都能解决。为此写段演示代码意义好像也不大,就这样吧。
文中示例代码见git:yaml-reader
End!!
发表评论