go-ini配置库
开发初衷
- 需要一个支撑读写注释的
INI
工具包 - 前身是
goconfig
,接口方法模仿了Windows API
func (c *ConfigFile)GetValue(section, key string)(string, error)
- 但有一些不足
- 对配置文件的内容规范比较严格,支持不够广泛
- 加载文件不支持附加选项,灵活性低
- 是学Go早期的产物,内部实现一团乱麻
- 当时没有版本的概念,改用
gopkg.in
路径另起炉灶
在线演示
GitHub
仓库:github.com/go-ini/ini- 演示内容:
- 加载一个配置文件,并获取其中的内容
- 直接映射配置到一个结构体上
- 对配置做一些修改,然后保存到另一个文件
加载一个配置文件,并获取其中的内容
main.go与conf.ini位于同一级目录下
main.go
package main
import (
"fmt"
"gopkg.in/ini.v1"
"log"
)
func main() {
cfg, err := ini.Load("conf.ini")
if err != nil {
log.Fatal("Failed to load:", err)
}
port := cfg.Section("server").Key("http_port").String()
fmt.Println("port:", port)
}
conf.ini
[server]
http_port = 3000
运行结构:
port: 3000
对配置做一些修改,然后保存到另一个文件
main.go
package main
import (
"fmt"
"gopkg.in/ini.v1"
"log"
)
func main() {
cfg, err := ini.Load("conf.ini")
if err != nil {
log.Fatal("Failed to load:", err)
}
port := cfg.Section("server").Key("http_port").String()
//Section() 获取对应的分区
fmt.Println("port:", port)
cfg.Section("server").Key("http_port").SetValue("3001")
err = cfg.SaveTo("conf2.ini")
if err != nil {
log.Fatal("Failed to save:", err)
}
}
conf2.ini
[server]
http_port = 3001
目录结构:
配置文件直接映射配置到一个结构体上
package main
import (
"fmt"
"gopkg.in/ini.v1"
"log"
)
type Server struct {
HttpPort int
}
func main() {
cfg, err := ini.Load("conf.ini")
if err != nil {
log.Fatal("Failed to load:", err)
}
//HttpPort在conf.ini未有对应的字段 需要进行映射
cfg.NameMapper = ini.TitleUnderscore //下文会提供视频地址 视频内关于源码的介绍
var s Server
err = cfg.Section("server").MapTo(&s)
if err != nil {
log.Fatal("Failed to map:", err)
}
fmt.Println("server:", s)
}
运行结果:
未加cfg.NameMapper = ini.TitleUnderscore
的情况下结果为:·· server: {0}
添加cfg.NameMapper = ini.TitleUnderscore
的情况下结果为:·· server: {3000}
与市面上其他库的比较
- 在
INI
相关库的横向比较中,其他库的功能过于基础,完全无法与之抗衡… - Viper:
支撑更丰富的配置格式,不仅限于
INI
,还支持JSON
,YAML
等等。支撑监控配置变更
支撑对环境变量的自动绑定
不支持配置内容到结构体的双向映射(无法具体到GO类型)
不支持
INI
特有的相关用法
有哪些特点和不足
- 特点:
- 支持用多种方法混合加载配置:
[]byte
,文件或者io.ReadCloser
- 支持注释读写操作
- 支持各种
INI
的流派:MySQL
、Git
、Python
、AWS
等等 - 为
Go
量身定制的结构体双向映射 - 自定义加载策略、数据验证、键名映射
- 支持用多种方法混合加载配置:
- 不足:
- 不支持配置监控
- 不支持
Marshaller
接口 - 不支持重名分区
- 不支持从网络地址加载
- 仅支持
UTF-8
编码
设计思路
- 不采用传统的AST解析方法
- 鉴于
INI
的语法相对简单,使用按行解析更为直观
- 鉴于
- 凡是可直接对应到某个具体
Go
类型的,均提供便利方法一步到位 - 在确保没有数据竞争的情况下,读性能要非常高
- 用于
i18n
工具包的底层存储方案,每次渲染可能有上百次读操作
- 用于
- 尊重配置文件的原始格式
- 保持文件时,若没有改动则要求输出一样的内容(空白符号除外)
性能一览
在进行基准测试的时候,如果加上数据静态检查,这个基准测试是不太准的,会慢上20倍左右。
源码速读
- 如何提升读性能:BlockMode、(Key).String vs (Key).Value
- 如何支持多种数据源:LoadSources
- 如何解析内容:(*File).parse
- 如何支持键名映射:NameMapper
- 如何支持结构体映射:(Section).MapTo、 (Section).ReflectForm
文章结尾视频链接 27:00-43:30
后续功能展望
- 支持配置监控
- 简化调用逻辑、内部确保线程安全
- 支持从网络地址加载
- 更好地配合应用集群拉取配置
- 支持
Marshaller
接口(v2)- 允许用户自定义映射逻辑和错误处理
其他
平时的学习方法-Tip:找一个需要的东西去做,然后你会遇到很多问题,然后你就去查找解决这一些列问题,一开始你可能会觉得是针对某一个特定的问题,但你完成了几个小项目之后,这些都是你积累下的经验,这些经验是可以融会贯通的,然后你去看书,在你看书的过程中就能过联想到大概会是一个怎样的运用场景,然后结合书中的实例,发现原来还可以这样用。
推荐读物:有开发几个小项目的经验之后阅读效果更好
- go并发编程——作为工具书查阅
- go语言圣经
- go语言实战
视频链接:#71 go-ini 配置库评析 by 无闻(unknwon)【 Go 夜读 】
相关文档:
本作品采用《CC 协议》,转载必须注明作者和本文链接