Go中解析配置文件demo

作者: ropon 分类: Go 发布时间: 2019-12-19 17:01
package main

import (
	"fmt"
	"io/ioutil"
	"reflect"
	"strconv"
	"strings"
)

// Config 日志文件结构体
type Config struct {
	Level    string `conf:"level"`
	Filepath string `conf:"filepath"`
	Filename string `conf:"filename"`
	Maxsize  int64  `conf:"maxsize"`
}

func parseConf(fileName string, result interface{}) (err error) {
	t := reflect.TypeOf(result)
	v := reflect.ValueOf(result)
	if t.Kind() != reflect.Ptr || v.Elem().Kind() != reflect.Struct {
		err = fmt.Errorf("result必须是一个指针且是结构体指针")
		return
	}
	data, err := ioutil.ReadFile(fileName)
	if err != nil {
		err = fmt.Errorf("打开配置文件%s失败", fileName)
		return
	}
	lineSlice := strings.Split(string(data), "\r\n")
	resMap := map[string]string{}
	for index, line := range lineSlice {
		//去除收尾空格
		line = strings.TrimSpace(line)
		//排查空行或注释行
		if line == "" || strings.HasPrefix(line, "#") {
			continue
		}
		//排查不含=的行
		eqIndex := strings.Index(line, "=")
		if eqIndex == -1 {
			err = fmt.Errorf("第%d行有语法错误", index+1)
			return
		}
		//排查没有key的行 比如 =dsfafads
		//Trim 去除收尾指定字符串
		//TrimSpace 去除收尾空格
		key := strings.ToLower(strings.TrimSpace(line[:eqIndex]))
		//去除首尾双引号"
		val := strings.Trim(strings.TrimSpace(line[eqIndex+1:]), "\"")
		if key == "" {
			err = fmt.Errorf("第%d行有语法错误", index+1)
			return
		}
		resMap[key] = val
	}
	//结构体反射 reflect.TypeOf(result) 下的方法
	//Elem()方法获取指针对应的值
	tElem := t.Elem()
	vElem := v.Elem()
	for i := 0; i < tElem.NumField(); i++ {
		// 取到结构体字段信息
		field := tElem.Field(i)
		// 通过字段名取到tag
		tagName := field.Tag.Get("conf")
		switch field.Type.Kind() {
		case reflect.String:
			//再找到值信息设置值
			vElem.Field(i).SetString(resMap[tagName])
		case reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
			//将任意类型转换为Int64
			val64, _ := strconv.ParseInt(resMap[tagName], 10, 64)
			vElem.Field(i).SetInt(val64)
		}
	}
	return
}

func main() {
	c := &Config{}
	err := parseConf("config.conf", c)
	if err != nil {
		fmt.Println(err)
		return
	}
	fmt.Println(c.Level)
	fmt.Println(c.Filename)
	fmt.Println(c.Filepath)
	fmt.Println(c.Maxsize)
}

如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!