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 },
]