go简单写个ini配置文件读取工具

直接上代码:

  1 package main
  2 
  3 import (
  4     "fmt"
  5     "io/ioutil"
  6     "reflect"
  7     "strconv"
  8     "strings"
  9 )
 10 
 11 type MysqlConfig struct {
 12     Address  string `ini:"address"`
 13     Port       int    `ini:"port"`
 14     UserName string `ini:"username"`
 15     PassWord string `ini:"password"`
 16 }
 17 
 18 type RedisConfig struct {
 19     Host      string `ini:"host"`
 20     Port      int    `ini:"port"`
 21     PassWord string `ini:"password"`
 22     DataBase int    `ini:"database"`
 23 }
 24 
 25 type Config struct {
 26     MysqlConfig `ini:"mysql"`
 27     RedisConfig `ini:"redis"`
 28 }
 29 
 30 func loadIni(fileName string, v interface{}) error {
 31     // 参数校验:v需为结构体指针类型
 32     t := reflect.TypeOf(v)
 33     if t.Kind() != reflect.Ptr || t.Elem().Kind() != reflect.Struct {
 34         return fmt.Errorf("v should be a struct ptr")
 35     }
 36 
 37     // 读取文件得到数据后立即关闭文件
 38     f, err := ioutil.ReadFile(fileName)
 39     if err != nil {
 40         return err
 41     }
 42     // 逐行获取文件内容,将值赋值给对应的结构体对象
 43     lineSlice := strings.Split(string(f), "\n")
 44     var structName string
 45     for index, line := range lineSlice {
 46         line = strings.TrimSpace(line)
 47         // 跳过注释和空行
 48         if strings.HasPrefix(line, ";") || strings.HasPrefix(line, "#") || len(line) == 0 {
 49             continue
 50         }
 51         // 以 [ 开头,为节点,需以 ] 结尾,且除空格外存在字符
 52         if strings.HasPrefix(line, "[") {
 53             if line[len(line) - 1] != ']' {
 54                 return fmt.Errorf("line:%d syntax error", index+1)
 55             }
 56             sectionName := strings.TrimSpace(line[1:len(line)-1])
 57             if len(sectionName) == 0 {
 58                 return fmt.Errorf("line:%d syntax error", index+1)
 59             }
 60             // 根据字符串sectionName去v里面根据反射找到对应的结构体
 61             for i :=0 ; i < t.Elem().NumField(); i ++ {
 62                 field := t.Elem().Field(i)
 63                 if sectionName == field.Tag.Get("ini") {
 64                     structName = field.Name
 65                     //fmt.Println(structName)
 66                     break
 67                 }
 68             }
 69         } else {
 70             // 不以 [ 开头,为以=分割的键值对
 71             if strings.Index(line, "=") == -1 || strings.HasPrefix(line, "=") {
 72                 return fmt.Errorf("line:%d syntax error", index+1)
 73             }
 74             // 根据struct名称找到对应结构体
 75             data := reflect.ValueOf(v)
 76             structValue := data.Elem().FieldByName(structName)  // 拿到嵌套结构体的值信息
 77             structType := structValue.Type()  // 拿到嵌套结构体的类型信息
 78             if structType.Kind() != reflect.Struct {
 79                 return fmt.Errorf("config struct field %s must be a struct", structName)
 80             }
 81             // 拆分键值对并赋值
 82             paramSlice := strings.Split(line, "=")
 83             key, value := strings.TrimSpace(paramSlice[0]), strings.TrimSpace(paramSlice[1])
 84             for x := 0; x < structType.NumField(); x ++ {
 85                 // 先拿到fieldType,fieldType中可以拿到field的值类型
 86                 fieldType := structType.Field(x)
 87                 if fieldType.Tag.Get("ini") == key {
 88                     // 根据field名称拿到field字段
 89                     fieldV := structValue.FieldByName(fieldType.Name)
 90                     // 给字段赋值
 91                     switch fieldType.Type.Kind() {
 92                     case reflect.String:
 93                         fieldV.SetString(value)
 94                     case reflect.Int,reflect.Int8,reflect.Int16,reflect.Int32,reflect.Int64:
 95                         valueInt, err := strconv.ParseInt(value, 10, 64)
 96                         if err != nil {
 97                             return fmt.Errorf("parseInt error, err:%v", err)
 98                         }
 99                         fieldV.SetInt(valueInt)
100                     case reflect.Float32:
101                         valueFloat, err := strconv.ParseFloat(value, 32)
102                         if err != nil {
103                             return fmt.Errorf("parseFloat error, err:%v", err)
104                         }
105                         fieldV.SetFloat(valueFloat)
106                     case reflect.Float64:
107                         valueFloat, err := strconv.ParseFloat(value, 64)
108                         if err != nil {
109                             return fmt.Errorf("parseFloat error, err:%v", err)
110                         }
111                         fieldV.SetFloat(valueFloat)
112                     case reflect.Bool:
113                         valueBool, err := strconv.ParseBool(value)
114                         if err != nil {
115                             return fmt.Errorf("parseBool error, err:%v", err)
116                         }
117                         fieldV.SetBool(valueBool)
118                     }
119                     break
120                 }
121             }
122         }
123     }
124     return nil
125 }
126 
127 func main() {
128     var config Config
129     fileName := "/home/xxx/data/demo_config/config.ini"
130     err := loadIni(fileName, &config)
131     if err != nil {
132         fmt.Printf("load ini failed, err:%v", err)
133     }
134     fmt.Println("mysql config:")
135     fmt.Printf("address:%s\tport:%d\tusername:%s\tpassword:%s\n", config.MysqlConfig.Address, config.MysqlConfig.Port, config.MysqlConfig.UserName, config.MysqlConfig.PassWord)
136 
137     fmt.Println("redis config:")
138     fmt.Printf("host:%s\tport:%d\tpassword:%s\tdatabase:%d\n", config.RedisConfig.Host, config.RedisConfig.Port, config.RedisConfig.PassWord, config.RedisConfig.DataBase)
139 }
原文地址:https://www.cnblogs.com/zzmx0/p/15612603.html