iGO实现之路 —— Config
本文为转载,原文: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 conf
import (
"strings"
"strconv"
"io"
"bufio"
"os"
)
上面的这些代码整合到一起就是ini_config.go的完整代码了。
测试
上面那些,也就简单的实现了配置文件的读取功能了。但是能不能用呢?我们简单的做个测试吧。
/example/config/app.config
中写一些简单的配置信息:
[default]
string = string
int = 10
int64 = 100000
float = 123.456
bool = 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