這是一個建立於 的文章,其中的資訊可能已經有所發展或是發生改變。
最近迷戀go語言,但我是個編程菜鳥,這個讀取參考了beego的config,只是半成品,不過能夠正常運行。
- 介面的設計
type Parser interface {Parse() error}type Config interface {GetString(string)stringParser}
目前只支援最小操作,解析和擷取。在讀取之前,要讓config執行個體化一個對象:
var config Configfunc RegisterConfig(mode,path string){switch mode{case "ini":config=ini.NewIniConfig(path)case "json":case "xml":default:panic("Dosn't Supported configure type.")}}
這樣,只要Iniconfig實現了config介面,就能將執行個體化的對象賦值給config,這個對象是全域的,外部調用config.Regi...之後,調用封裝好的操做即可擷取執行個體,實現功能。
全域實現:util.go
package configimport "mytools/config/ini"type Parser interface {Parse() error}type Config interface {GetString(string)stringParser}var config Configfunc RegisterConfig(mode,path string){switch mode{case "ini":config=ini.NewIniConfig(path)case "json":case "xml":default:panic("Dosn't Supported configure type.")}}func GetConfig()*Config{return &config}
IniConfig實現
package iniimport ("os""sync""bufio""io""bytes""strings""log")var(DEFAULT_SECTION stringCOMMENT []byteSEPARATOR []byte//SECTION_START string//SECTION_END string)//const(//LEFT = iota//RIGHT//)func init(){DEFAULT_SECTION="default"COMMENT=[]byte{'#'}SEPARATOR=[]byte{'='}}//type EntryConfig struct {//IsAlign bool //對齊//AlignType int //對齊類型//}type IniEntry struct {value interface {}}type IniConfig struct {filename stringsection map[string]*IniSectionsync.RWMutex}func NewIniConfig(path string) *IniConfig{config:=&IniConfig{path,make(map[string]*IniSection),sync.RWMutex{}}config.section[DEFAULT_SECTION]=NewIniSection()return config}func (c *IniConfig)Parse() error{file,err:=os.Open(c.filename)if err!=nil {return err}c.Lock()defer c.Unlock()defer file.Close()buf:=bufio.NewReader(file)section:=DEFAULT_SECTIONvar bufRead intfor{//讀取一行緩衝line,_,err:=buf.ReadLine()bufRead = bufRead + len(line)if err==io.EOF{//讀到檔案結尾,退出迴圈break}if bytes.Equal(line,[]byte("")){//空行直接跳過迴圈continue}//刪除行兩端的空白字元line=bytes.TrimSpace(line)if bytes.HasPrefix(line,COMMENT){//注釋行暫時不做處理continue}if bytes.HasPrefix(line,[]byte("["))&&bytes.HasSuffix(line,[]byte("]")){//section處理//現在line確定為"[sectioname]"//不知道有沒有合法性檢查section=string(line[1:len(line)-1])section=strings.ToLower(section)if _,ok:=c.section[section];!ok{c.section[section]=NewIniSection()}}else{//key=value處理pair:= bytes.SplitN(line,SEPARATOR,2)key:= pair[0]val:=pair[1]if _,ok:=c.section[section];!ok{c.section[section]=NewIniSection()}log.Println(key,val)c.section[section].addEntry(string(key),string(val))}}return nil}func (c *IniConfig)RemoveSection(key string) error{return nil}func (c *IniConfig)GetString(k string) string{s:=strings.Split(k,":")var sec stringvar key stringif len(s)==1{sec=DEFAULT_SECTIONkey=s[0]log.Println(sec,key)}else{sec=s[0]key=s[1]log.Println(sec,key)}if v,ok:=c.section[sec].getEntry(key).(string);ok{return v}return ""}
首先看結構,Ini檔案最基本的組成由注釋,模組,項三個部分,其中,注釋行可能由特定的字元開頭,比如“#”,“;”等,現在預設是"#",如果要支援自訂字元,添加介面和check操作就能實現。在模組載入時我們就已經定義好了預設操作。參見init函數。
在回過頭看看section,iniconfig是一個深度為2的樹結構,每個樹的跟節點是sectionname,子節點是配置項key=value,預設有一個defaultsection。
在解析方面,逐行讀取,然後根據ini檔案特點,處理注釋行,注釋段(未實現),section,和項,之後把他們轉換成資料結構儲存在Iniconfig中,只要調用GetString即可拿到配置項,文法為"section:key"。
那麼,先到這裡吧。
菜鳥輕噴。。。。。