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 }