config
https://developer.aliyun.com/article/611301
一些mysql或者日志路径的信息需要放在配置文件中。那么本博文主要介绍go对toml文件的解析。
使用了 "github.com/BurntSushi/toml" 标准库。
1 toml文件的写法
[Mysql] UserName = "sonofelice" Password = "123456" IpHost = "127.0.0.1:8902" DbName = "sonofelice_db"
2 对toml文件的解析
为了要解析上面的toml文件,我们需要定义与之对应的struct:
type Mysql struct { UserName string Password string IpHost string DbName string }
那么其实可以写这样一个conf.go
package conf import ( "nlu/log" "github.com/BurntSushi/toml" "flag" ) var ( confPath string // Conf global Conf = &Config{} ) // Config . type Config struct { Mysql *Mysql } type Mysql struct { UserName string Password string IpHost string DbName string } func init() { flag.StringVar(&confPath, "conf", "./conf/conf.toml", "-conf path") } // Init init conf func Init() (err error) { _, err = toml.DecodeFile(confPath, &Conf) return }
通过简单的一行代码toml.DecodeFile(confPath, &Conf),就把解析好的struct存到了&Conf里面
那么我们在main里面调用一下init:
func main() { flag.Parse() if err := conf.Init(); err != nil { log.Error("conf.Init() err:%+v", err) } mysqlConf := conf.Conf.Mysql fmt.Println(mysqlConf.DbName) }
然后运行一下main函数,就可以看到控制台中打印出了我们在conf.toml中配置的
sonofelice_db
配置文件是一种非常基础的文件格式,但远没有数据文件格式(如 SQLite
)、文档文件格式(如 Markdown
)、编程语言(如 JavaScript
)、甚至二进制文件格式(如 PNG
)需求那么复杂。
只要严谨但不严苛、支持必要的数据类型和嵌套,又易于人类手工直接阅读和编辑就可以了。
但就是这样一种广泛需要而又简单的应用场景,却反而长期以来一直没有一种足够好的文件格式。
INI(.ini
)文件是一种非常原始的基础形式,但各家有各家的用法,而且它最多只能解决一层嵌套。只适合非常非常简单的配置文件,一旦需要两层嵌套,或需要数组,就力不从心了。
; 最简单的结构
a = a;
b = b; 这些等号后面的值是字符串(句末分号不是必须的;它后面的都是注释)
; 稍微复杂一点的单层嵌套结构
[c]
x = c.x
y = c.y
[d]
x = d.x
y = d.y
JSON(.json
)是一种非常好的数据存放和传输的格式,但阅读和编辑它实在不方便。即便 JSON5
(.json5
- ECMAScript 5.1 JSON
)这种扩展格式允许了你像写 JavaScript
对象那样书写裸键名、允许尾逗号,并且可以有注释,写多行字符串依然麻烦。即便它将来加上了多行字符串语法,依然不行,因为它虽然是基于括号嵌套语法的层级关系,在不缩进的情况下,却根本没法阅读。
{
"a": "a",
"b": "b",
"c":{
"x": "c.x",
"y": "c.y"
},
"d":{
"x": "d.x",
"y": "d.y"
},
"e":[
{ "x":"e[0].x", "y":"e[0].y" },
{ "x":"e[1].x", "y":"e[1].y" }
]
}
YAML(.yaml
或 .yml
)干脆将 JSON
中有了不够、没有不行的括号结构去掉了,只保留缩进。但编辑和阅读它总令人非常慌张,生怕数错了层次(实际上,对于阅读,语法关键字并不是越小越好)。而且在不支持统一缩进、反缩进、自动在换行时缩进的编辑环境下,这非常麻烦——这本来对编程语言来说不是什么事,但配置文件最常用的使用场景却恰恰是这样。
另外,YAML
的语法实在太多了,而且不是循序渐进的,即便你不需要复杂的功能,为了保证自己的简单功能不出错,也要对那些复杂的语法有所了解并加以避免(比如究竟什么键名可以不加引号,什么字符串可以不加引号;你总不能为了避免歧义全都加上引号,那和 JSON
也就差球不多了)。更糟的是,纵使如此复杂,想要配置一段精确的多行字符串(精确控制首尾空行数)时,却显得力不从心。再加上缩进问题,编辑多行文本实在烦不胜烦。如果你还需要转义字符……
a1: abc # string
a2: true # boolean
b1: nil # string
b2: null # null
b3: NULL # null
b4: NuLL # string
b5: Null # null
c:
x: c.x
y: c.y
d:
x: d.x
y: d.y
e:
- x: e[0].x
y: e[0].y
- x: e[1].x
y: e[1].y
终于,TOML(.toml
)横空出世。它彻底放弃了括号或缩进的底层原理,而是采取了显式键名链的方式。
为了方便(同时看起来更清楚——这种读和写的契合非常关键!),你可以指定小节名。妙的是,小节名也是可以链式声明的。
另外,某些数据可能使用内联数组或表更合适以避免臃肿,这也是支持的。
a = "a"
b = "b"
c.x = "c.x"
c.y = "c.y"
[d]
x = "d.x"
y = "d.y"
[[e]]
x = "e[0].x"
y = "e[0].y"
[[e]]
x = "e[1].x"
y = "e[1].y"
[f.A]
x.y = "f.A.x.y"
[f.B]
x.y = """
f.
B.
x.
y
"""
[f.C]
points = [
{ x=1, y=1, z=0 },
{ x=2, y=4, z=0 },
{ x=3, y=9, z=0 },
]