最近遇到一个需求, 需要做一个配置文件读取功能,用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,这样就实现了通用的配置文件读取
发表回复