這是一個建立於 的文章,其中的資訊可能已經有所發展或是發生改變。
注意事項
本部落格隸屬於 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.comsearch=http://%(google)s
當您使用 %()s
包含某個鍵名來作為值的時候,goconfig 會去尋找相應的鍵的值進行替換;如果被替換的鍵的值還有這樣的嵌套,則會遞迴執行替換。該操作最多允許 200 層的嵌套。此時,鍵 search
真正的值為 http://www.google.com
。要注意的是,被包含的鍵可以是位於 DEFAULT
分區或同一分區的,出現順序任意。
子孫分區覆蓋讀取
在檔案 conf3.ini
中,有如下配置:
[parent]name=johnrelation=fathersex=maleage=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