[golang]自己动手实现ini文件读取

前端之家收集整理的这篇文章主要介绍了[golang]自己动手实现ini文件读取前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。

最近迷恋go语言,但我是个编程菜鸟,这个读取参考了beego的config,只是半成品,不过能够正常运行。

  1. 接口的设计
type Parser interface {
	Parse() error
}

type Config interface {
	GetString(string)string
	Parser
}

目前只支持最小操作,解析和获取。在读取之前,要让config实例化一个对象:

var config Config

func 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 config

import "mytools/config/ini"

type Parser interface {
	Parse() error
}

type Config interface {
	GetString(string)string
	Parser
}

var config Config

func 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 ini

import (
	"os"
	"sync"
	"bufio"
	"io"
	"bytes"
	"strings"
	"log"
)

var(
	DEFAULT_SECTION string
	COMMENT []byte
	SEPARATOR []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 string
	section map[string]*IniSection
	sync.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_SECTION
	var bufRead int
	for{
		//读取一行缓存
		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 string
	var key string
	if len(s)==1{
		sec=DEFAULT_SECTION
		key=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"。
那么,先到这里吧。

菜鸟轻喷。。。。。

猜你在找的Go相关文章