本文为转载,原文:iGO实现之路 —— Config
Golang
介绍
相信大多数的程序员在使用各种框架开发的时候,都会有一个配置文件让我们做一些配置,比如说数据库的配置,缓存的配置,调试的配置等等,这些配置只要我们填写之后就会生效。
今天,我就用go语言实现是个读取配置文件的小模块。可能并不是非常的完成,或者还会存在一些不安全的因素。这里我将我的实现写出来,望发现问题的同学们提出来,我们大家共同进步。
源码地址
实现
config 模块的文件列表如下图所示:
文件列表
conf
目录为功能模块example
目录为测试代码
功能实现
config.go
由于我们的配置文件类型可能是多种多样的,比如ini,json等。所以,我首先得做一个Config的接口:
type Config interface{ GetString(string) string GetInt(string)(int, error) GetInt64(string)(int64, error) GetFloat(string)(float64, error) GetBool(string)(bool, error)}
从代码中看,我们的接口比较简单,就是一些从配置文件中读取各种类型的值,这里先暂时支持string,int,int64,float,bool类型的数据读取,后续如有需要再更新。
有了接口,就便于我们同意操作了。下面我们再做一个实例化的函数,这个就有点类型简单工厂模式了。根据参数创建不同类型的实例:
func NewConfig(adapter, filename string) (Config, error){ path, err := GetCurrentPath(filename) if err != nil{ return nil, err } switch adapter{ case "ini": return GetIniConfig(path) default: return nil, errors.New("系统暂未处理该类型的配置文件") } }
该函数有2个参数,adapter为我们适配的配置文件类型,如ini, json等。filename为我们的配置文件的相对路径。
代码通过不同的adapter返回不同的实例。该函数中调用了个GetCurrentPath函数。
下面,我们看下GetCurrentPath函数的实现:
func GetCurrentPath(filename string) (path string, err error ){ path, err = filepath.Abs(filename) if err != nil { return } path = strings.Replace(path, "\\", "/", -1) path = strings.Replace(path, "\\\\", "/", -1) return}
该函数的作用是将配置文件的相对路径转换为绝对路径。
至此,我们的公用的代码已经完成了。接下来就是各种不同的配置文件的实现了,也就是各种对于Config接口实现的方案。
完整的config.go代码如下:
package conf import ( "strings" "errors" "path/filepath") type Config interface{ GetString(string) string GetInt(string)(int, error) GetInt64(string)(int64, error) GetFloat(string)(float64, error) GetBool(string)(bool, error) } func NewConfig(adapter, filename string) (Config, error){ path, err := GetCurrentPath(filename) if err != nil{ return nil, err } switch adapter{ case "ini": return GetIniConfig(path) default: return nil, errors.New("系统暂未处理该类型的配置文件") } } func GetCurrentPath(filename string) (path string, err error ){ path, err = filepath.Abs(filename) if err != nil { return } path = strings.Replace(path, "\\", "/", -1) path = strings.Replace(path, "\\\\", "/", -1) return}
ini
ini_config.go
INI文件格式是某些平台或软件上的配置文件的非正式标准,以节(section)和键(key)构成,常用于微软Windows操作系统中。这种配置文件的文件扩展名多为INI,故名。
INI是英文“初始化”(initialization)的缩写。正如该术语所表示的,INI文件被用来对操作系统或特定程序初始化或进行参数设置。
既然知道了ini文件,那么我们就看看怎么去读取其配置吧。
先看下对于IniConfig的结构体定义:
type IniConfig struct{ ConfigMap map[string]string strcet string}
从config.go代码文件中的NewConfig函数中,我们看到了这样一个函数GetIniConfig
,而该函数就是对于ini文件配置的初始化:
func GetIniConfig(filename string)(*IniConfig, error){ middle := "." config := new(IniConfig) config.ConfigMap = make(map[string]string) //打开文件 file, err := os.Open(filename) if err != nil{ return nil, err } defer file.Close() read := bufio.NewReader(file) for{ b, _, err := read.ReadLine() if err != nil { if err == io.EOF{ break } return nil, err } str := strings.TrimSpace(string(b)) //配置文件中的注释 if strings.Index(str, "#") == 0{ continue } //配置文件中的前缀处理 n1 := strings.Index(str, "[") n2 := strings.LastIndex(str, "]") if n1 > -1 && n2 > -1 && n2 > n1 + 1{ config.strcet = strings.TrimSpace(str[n1 + 1 : n2]) continue } if len(config.strcet) < 1{ continue } // eqIndex := strings.Index(str, "=") if eqIndex < 0{ continue } eqLeft := strings.TrimSpace(str[0:eqIndex]) if len(eqLeft) < 1{ continue } eqRight := strings.TrimSpace(str[eqIndex+1:]) pos := strings.Index(eqRight,"\t#") val := eqRight if pos > -1{ val = strings.TrimSpace(eqRight[0:pos]) } pos = strings.Index(eqRight, " #") if pos > -1{ val = strings.TrimSpace(eqRight[0:pos]) } pos = strings.Index(eqRight, "\t//") if pos > -1{ val = strings.TrimSpace(eqRight[0:pos]) } pos = strings.Index(eqRight, " //") if pos > -1{ val = strings.TrimSpace(eqRight[0:pos]) } if len(val) < 1{ continue } key := config.strcet + middle + eqLeft config.ConfigMap[key] = strings.TrimSpace(val) } return config, nil }
然后再有一个按key来获取配置的val的字符串的函数:
func (self *IniConfig) Get(key string)string{ v, ok := self.ConfigMap[key] if ok{ return v } return ""}
剩下来就是对于Config接口的实现了:
func (self *IniConfig) GetString(key string)string{ return self.Get(key) } func (self *IniConfig) GetInt(key string)(int, error){ return strconv.Atoi(self.Get(key)) } func (self *IniConfig) GetInt64(key string)(int64, error){ return strconv.ParseInt(self.Get(key), 10, 64) } func (self *IniConfig) GetFloat(key string)(float64, error){ return strconv.ParseFloat(self.Get(key), 64) } func (self *IniConfig) GetBool(key string)(bool, error){ return strconv.ParseBool(self.Get(key)) }
ini_config.go的实现就这些。当然了,package和import也是肯定有的啦:
package confimport ( "strings" "strconv" "io" "bufio" "os")
上面的这些代码整合到一起就是ini_config.go的完整代码了。
测试
上面那些,也就简单的实现了配置文件的读取功能了。但是能不能用呢?我们简单的做个测试吧。/example/config/app.config
中写一些简单的配置信息:
[default]string = stringint = 10int64 = 100000float = 123.456bool = true
然后在/example/test_config.go
读取试一下:
package main import( "fmt" "igo/conf") func main(){ config,err := conf.NewConfig("ini", "config/app.config") if err != nil{ fmt.Println(err.Error()) return } strVal := config.GetString("default.string") fmt.Println("string value:", strVal) intVal, err := config.GetInt("default.int") if err != nil{ fmt.Println("get int value error: ", err.Error()) } fmt.Println("int value: ", intVal) int64Val, err := config.GetInt64("default.int64") if err != nil{ fmt.Println("get int64 value error: ", err.Error()) } fmt.Println("int64 value: ", int64Val) floatVal, err := config.GetFloat("default.float") if err != nil{ fmt.Println("get float value error: ", err.Error()) } fmt.Println("float value: ", floatVal) boolVal, err := config.GetBool("default.bool") if err != nil{ fmt.Println("get bool value error: ", err.Error()) } fmt.Println("bool value: ", boolVal) }
结果如下:
config测试结果
完
转载请注明出处:
iGO实现之路 —— Config
共同学习,写下你的评论
评论加载中...
作者其他优质文章