golang 使用reflect包实现ini文件解析功能
config.ini
[mysqld]
user = mysql
password = abc123
ip = 10.0.0.1
port = 3306
main.go
package main
import (
"errors"
"fmt"
"io/ioutil"
"reflect"
"strconv"
"strings"
)
type MysqlConfig struct {
Ip string `ini:"ip"`
User string `ini:"user"`
Password string `ini:"password"`
Port int `ini:"port"`
}
type Config struct {
MysqlConfig `ini:"mysqld"`
}
func loadIni(filename string, data interface{}) (err error) {
t := reflect.TypeOf(data)
if t.Kind() != reflect.Ptr && t.Kind() != reflect.Struct {
err = errors.New("type error should be struct ptr ")
return err
}
file, err := ioutil.ReadFile(filename)
if err != nil {
err = fmt.Errorf("open file error %v\n", err)
return err
}
lineSlice := strings.Split(string(file), "\r\n")
var section string
var structName string
for idx, line := range lineSlice {
line = strings.TrimSpace(line)
if len(line) == 0 {
continue
}
if strings.HasPrefix(line, ";") || strings.HasPrefix(line, "#") {
continue
}
if strings.HasPrefix(line, "[") {
if line[0] == '[' && line[len(line)-1] == ']' && len(line) > 2 {
section = line[1 : len(line)-1]
}
for i := 0; i < t.Elem().NumField(); i++ {
field := t.Elem().Field(i)
if section == field.Tag.Get("ini") {
structName = field.Name
}
}
} else {
if strings.Index(line, "=") == -1 || strings.HasPrefix(line, "=") {
err = fmt.Errorf("line:%d syntax error ", idx+1)
return
}
index := strings.Index(line, "=")
key := strings.TrimSpace(line[:index])
value := strings.TrimSpace(line[index+1:])
v := reflect.ValueOf(data)
sValue := v.Elem().FieldByName(structName)
sType := sValue.Type()
if sType.Kind() != reflect.Struct {
err = fmt.Errorf("should be struct")
return err
}
var fname string
var fieldType reflect.StructField
for i := 0; i < sValue.NumField(); i++ {
fieldName := sType.Field(i)
fieldType = fieldName
if fieldName.Tag.Get("ini") == key {
fname = fieldName.Name
break
}
}
fieldObj := sValue.FieldByName(fname)
switch fieldType.Type.Kind() {
case reflect.String:
fieldObj.SetString(value)
case reflect.Int, reflect.Int16, reflect.Int32, reflect.Int64:
var valueInt int64
valueInt, err := strconv.ParseInt(value, 10, 64)
if err != nil {
return err
}
fieldObj.SetInt(valueInt)
case reflect.Bool:
var valueBool bool
valueBool, err := strconv.ParseBool(value)
if err != nil {
return err
}
fieldObj.SetBool(valueBool)
case reflect.Float32, reflect.Float64:
var valueFloat float64
valueFloat, err := strconv.ParseFloat(value, 64)
if err != nil {
return err
}
fieldObj.SetFloat(valueFloat)
}
}
}
return
}
func main() {
var config Config
err := loadIni("src/github.com/chenjiaona999/home/config.ini", &config)
if err != nil {
fmt.Println(err)
}
fmt.Println(
config.MysqlConfig.Ip,
config.MysqlConfig.Password,
config.MysqlConfig.Port,
config.MysqlConfig.User,
)
}