使用Go写一个通用的配置文件解析器

最近遇到一个需求, 需要做一个配置文件读取功能,用key:values的形式返回给前端, 但是我们有5种服务

然后如果5种服务的配置文件都不一样,比如有的以:分割, 有的以=分割,有的是csv,甚至有的配置项我们不希望暴露给用户, 那么冗余代码会非常多, 所以我就想优化一下代码逻辑

首先我们总结一下读取配置文件的功能顺序

  • 打开配置文件
  • 按行读取
  • 不符合条件的行跳过
  • 以指定的分隔符切割, 拿到配置的key, value
  • 返回

所以冗余的代码在于

  • 打开文件
  • 按行读取

所以我们就把这两个冗余代码给抽象出来

func (c *Collector) GetConfigHandler(service string) (map[string]string, error) {
	//拿到配置文件路径
	configFilePath, ok := configFilePathMap[service]
	if !ok {
		return map[string]string{}, code.ServiceNotNout
	}
	var (
		err  error
		data = map[string]string{}
		file *os.File
		k, v string
	)
	//打开文件
	if file, err = os.Open(configFilePath); err != nil {
		return data, err
	}
	defer file.Close()
	//拿到处理函数
	handler, ok := configFileHandlerMap[service]
	if !ok {
		return data, code.HandlerNotFind
	}
	//文件主转为buffio
	bufF := bufio.NewReader(file)
	for {
		//逐行读取
		line, _, _err := bufF.ReadLine()
		if _err != nil {
			if _err == io.EOF {
				break
			} else {
				return data, _err
			}
		}
		strLine := string(line)
		//把行内容送往对应的处理函数
		if k, v = handler(strLine); k == "" {
			continue
		}
		//拿到处理后的结果赋值给map
		data[k] = v
	}
	return data, nil
}

configFilePathMap就是定义了每一个服务的配置文件路径

configFileHandlerMap里就是每一个服务对应的处理函数, 下面是一个例子

func HwmConfigParse(strLine string) (string, string) {
	if strings.HasPrefix(strLine, "#") {
		return "", ""
	}
	if !strings.Contains(strLine, "=") {
		return "", ""
	}
	tmp := strings.Split(strLine, "=")
	return strings.TrimSpace(tmp[0]), strings.TrimSpace(tmp[1])

}

当行内容以#开头时,说明这是注释,我们跳过

当内容包含=号时, 说明这是配置行,然后我们用=号切割 把配置key和value返回

当我们的解析函数遇到调用处理函数返回的是””, “”时,意味着这行需要跳过, 否则我们就把返回值赋值给map,这样就实现了通用的配置文件读取


评论

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注