這是一個建立於 的文章,其中的資訊可能已經有所發展或是發生改變。
注意事項
本部落格隸屬於 goconfig - 課時 1:goconfig 使用解析 請注意配套使用。
本博文為 goconfig - Go 語言 INI 解析器的配套部落格,旨在通過文字結合程式碼範例對該庫的使用方法和案例進行講解,便於各位同學更好地使用和深入瞭解。
庫簡介
goconfig 是一個由 Go 語言開發的針對 Windows 下常見的 INI 格式的設定檔解析器。該解析器在涵蓋了所有 INI 檔案操作的基礎上,又針對 Go 語言實際開發過程中遇到的一些需求進行了擴充。相對於其它 INI 檔案解析器而言,該解析器最大的優勢在於對注釋的極佳支援;除此之外,支援多個設定檔覆蓋載入也是非常特別但好用的功能。
下載安裝
您可以通過以下兩種方式下載安裝 goconfig:
gopm get github.com/Unknwon/goconfig
或
go get github.com/Unknwon/goconfig
API 文檔
請移步 Go Walker。
基本使用方法
範例程式碼
一般來說,INI 格式的檔案均以 .ini 為尾碼,但您可以使用任意尾碼,這並不影響您使用該庫進行解析。在本例中,我們使用 conf.ini 作為我們的設定檔。
載入設定檔
要操作某個設定檔,需要先將其載入到記憶體中,我們需要調用 LoadConfigFile 函數來完成該操作:
cfg, err := goconfig.LoadConfigFile("conf.ini")
設定檔的檔案名稱可以寫相對路徑或絕對路徑,該函數傳回值分別為 ConfigFile 和 error 類型。如果載入操作發生錯誤,則變數 cfg 為 nil;否則 err 為 nil。載入完成之後,我們就可以通過操作變數 cfg 來對設定檔的資料進行操作。要注意的是,載入完成後所有資料均已存入記憶體,任何對檔案的修改操作都不會影響到已經擷取到的對象。也就是說,此時對檔案的修改是不會影響到 cfg 這個對象裡的資料的。
基本讀寫操作
通過 GetValue 方法可實現最基本的讀取操作。在本例中,鍵 key_default 屬於未命名的分區(section),則 goconfig 在解析器將它直接歸於名為 DEFAULT 的分區。當我們想要擷取它的值的時候,可以進行如下操作:
value, err := cfg.GetValue(goconfig.DEFAULT_SECTION, "key_default")
第一個傳回值為 string 類型,即取到的值;第二個傳回值為 error 類型,當發生錯誤時不為 nil。
除了讀取之外,還可以進行設定值操作:
isInsert := cfg.SetValue(goconfig.DEFAULT_SECTION, "key_default", "這是新的值")
該方法傳回值類型為 bool 類型,表示是否為插入操作。如果值為 true,表明該鍵之前未存在,現在插入成功;否則表示該鍵之前已經存在,它的值現在被重寫了。
如果您覺得每次都調用 goconfig.DEFAULT_SECTION 來表示 DEFAULT 分區非常繁瑣,您也可以直接使用空白字串來代表 DEFAULT 分區:
value, err = cfg.GetValue("", "key_default")
以上代碼也可以達到相同的效果。
除了使用等號作為索引值之間的分隔字元之外,冒號也是允許的:
key_super2 : 測試值
注釋讀寫操作
雖然大多數情況下程式都只從 INI 檔案進行資料的讀取操作,但偶爾會需要實現寫入到檔案的操作。此時,其餘所有的解析器都會將注釋給過濾掉;當注釋是設定檔各項說明的重要依據時,這種做法顯然是不可取的。因此,完整地儲存檔案中的注釋,並提供在程式中對注釋進行操作的 API 不可謂不是 goconfig 的一大特色。
goconfig 允許您的設定檔以分號 ; 或井號 # 為開頭在單獨的一行作為注釋:
; 以分號開頭的均為注釋行 # 以井號開頭的也為注釋行
但不可以在某一行的中間:
key_default = 預設節的一個鍵 # 注釋必須單獨佔行,此處的注釋無效
通過 goconfig 提供的 API,您可以操作某個分區或鍵的注釋。
擷取某個分區的注釋:
comment := cfg.GetSectionComments("super")
擷取某個鍵的注釋:
comment = cfg.GetKeyComments("super", "key_super")
這兩個方法均返回 string 類型的傳回值。
設定某個鍵的注釋:
v := cfg.SetKeyComments("super", "key_super", "# 這是新的鍵注釋")
設定某個分區的注釋:
v = cfg.SetSectionComments("super", "# 這是新的分區注釋")
上面兩個方法的傳回值都是 bool 類型。若為 true 表示注釋被插入或刪除(當傳入的參數為空白字串時);為 false 表示注釋已存在,現在被重寫。
類型轉換讀取
goconfig 提供以類型命名的一些方法,例如 Int、Int64 和 Bool 等等,這些方法會返回非 string 類型的值以及一個 error 類型的傳回值表示是否發生錯誤:
vInt, err := cfg.Int("must", "int")
第一個傳回值為 int 類型,第二個傳回值為 error 類型。
Must 系列方法
Must 系列方法是用於避免檢查 error 類型所造成的代碼臃腫,簡化資料擷取流程。這些方法均已 Must 字元開頭,如 MustInt、MustInt64和 MustBool 等等。這些方法一定會返回指定類型的值,若發生錯誤,則返回零值,不會發生錯誤:
vBool := cfg.MustBool("must", "bool")
該方法傳回值為 bool 類型。
刪除指定索引值
當您想要拋棄某個鍵時,可以通過 DeleteKey 方法來刪除某個鍵:
ok := cfg.DeleteKey("must", "string")
該方法傳回值為 bool 類型,用於表示刪除操作是否成功(若鍵不存在則會表示為不成功)。
儲存設定檔
當完成操作需要將資料寫回硬碟時,可以使用 SaveConfigFile 函數來將 ConfigFile 對象以字串的形式儲存到檔案系統中:
err = goconfig.SaveConfigFile(cfg, "conf_save.ini")
您需要指定要儲存的對象和檔案名稱,該方法返回一個 error 類型的值。
進階提示
範例程式碼
上一小結展示了如果使用 goconfig 完成常見的 INI 檔案操作,本小節則將著重介紹 goconfig 庫為大家帶來的一些擴充功能。
多檔案覆蓋載入
函數 LoadConfigFile 其實可以接受多個 string 類型的參數來表示要載入的多個設定檔名,並根據次序進行覆蓋式地載入:
cfg, err := goconfig.LoadConfigFile("conf.ini", "conf2.ini")
在本例中,如果 conf.ini 和 conf2.ini 中同時出現相同分區和鍵名時,則只會擷取到 conf2.ini 檔案中的值。
如果在程式運行途中發現需要增加設定檔,則可通過方法 AppendFiles 實現追加操作:
err = cfg.AppendFiles("conf3.ini")
設定檔重載
若外部檔案發生修改,可通過調用方法進行快速重載:
err = cfg.Reload()
該方法返回一個 error 類型的值表示操作是否成功。
為 Must 系列方法設定預設值
藉助 Go 語言變參的功能,當 Must 系列方法擁有三個參數時,則第三個參數即為擷取失敗時的預設值:
vBool := cfg.MustBool("must", "bool404", true)
本例中鍵名為 bool404 根本不存在,則會採用 true 作為傳回值。
遞迴讀取索引值
在檔案 conf3.ini 中,預設分區有兩個鍵如下:
google=www.google.com search=http://%(google)s
當您使用 %(<key>)s 包含某個鍵名來作為值的時候,goconfig 會去尋找相應的鍵的值進行替換;如果被替換的鍵的值還有這樣的嵌套,則會遞迴執行替換。該操作最多允許 200 層的嵌套。此時,鍵 search 真正的值為 http://www.google.com。要注意的是,被包含的鍵可以是位於DEFAULT 分區或同一分區的,出現順序任意。
子孫分區覆蓋讀取
在檔案 conf3.ini 中,有如下配置:
[parent] name=john relation=father sex=male age=32 [parent.child] age=3
當我們擷取 parent.child 分區中的鍵 age 時,我們會得到 3;但當我們想要擷取 sex 時,正常情況下應該為擷取失敗,不過,goconfig 會發現 parent.child 還有父分割 parent,因為 parent.child 使用了半形符號 . 來實現分級。這時候,擷取 sex 會得到 male。
自增鍵名擷取
在檔案 conf3.ini 中,有如下配置:
[auto increment] -=hello -=go -=config
由於使用 - 作為鍵名,則 goconfig 在解析時,會將它翻譯成自增數字,從 1 開始。在本例中,上面的鍵在對象中會被儲存為:
#1: hello #2: go #3: config
要注意的是,計數只在同個分區內有效,新的分區又會從 1 開始重新計數。
擷取整個分區
如果您想要直接操作某個分區,可通過方法 GetSection 來返回一個類型為 map[string]string 的值,其包含了相應分區的所有索引值對:
sec, err := cfg.GetSection("auto increment")
總結
goconfig 包的 API 提供非常全面,用法非常簡單,但核心代碼並不多,各位同學有興趣的可以閱讀其原始碼。
使用案例
- gopm
- beego - i18n
- beeweb
- wetalk
- gowalker