package main
import (
"errors"
"fmt"
"reflect"
"strconv"
"time"
)
type User struct {
Name string
Age int8
Date time.Time
}
func main() {
data := make(map[string]interface{})
data["Name"] = "张三"
data["Age"] = 26
data["Date"] = "2015-09-29 00:00:00"
result := &User{}
err := FillStruct(data, result)
fmt.Println(err, fmt.Sprintf("%+v", *result))
}
//用map填充结构
func FillStruct(data map[string]interface{}, obj interface{}) error {
for k, v := range data {
err := SetField(obj, k, v)
if err != nil {
return err
}
}
return nil
}
//用map的值替换结构的值
func SetField(obj interface{}, name string, value interface{}) error {
structValue := reflect.ValueOf(obj).Elem() //结构体属性值
structFieldValue := structValue.FieldByName(name) //结构体单个属性值
if !structFieldValue.IsValid() {
return fmt.Errorf("No such field: %s in obj", name)
}
if !structFieldValue.CanSet() {
return fmt.Errorf("Cannot set %s field value", name)
}
structFieldType := structFieldValue.Type() //结构体的类型
val := reflect.ValueOf(value) //map值的反射值
var err error
if structFieldType != val.Type() {
val, err = TypeConversion(fmt.Sprintf("%v", value), structFieldValue.Type().Name()) //类型转换
if err != nil {
return err
}
}
structFieldValue.Set(val)
return nil
}
//类型转换
func TypeConversion(value string, ntype string) (reflect.Value, error) {
if ntype == "string" {
return reflect.ValueOf(value), nil
} else if ntype == "time.Time" {
t, err := time.ParseInLocation("2006-01-02 15:04:05", value, time.Local)
return reflect.ValueOf(t), err
} else if ntype == "Time" {
t, err := time.ParseInLocation("2006-01-02 15:04:05", value, time.Local)
return reflect.ValueOf(t), err
} else if ntype == "int" {
i, err := strconv.Atoi(value)
return reflect.ValueOf(i), err
} else if ntype == "int8" {
i, err := strconv.ParseInt(value, 10, 64)
return reflect.ValueOf(int8(i)), err
} else if ntype == "int32" {
i, err := strconv.ParseInt(value, 10, 64)
return reflect.ValueOf(int64(i)), err
} else if ntype == "int64" {
i, err := strconv.ParseInt(value, 10, 64)
return reflect.ValueOf(i), err
} else if ntype == "float32" {
i, err := strconv.ParseFloat(value, 64)
return reflect.ValueOf(float32(i)), err
} else if ntype == "float64" {
i, err := strconv.ParseFloat(value, 64)
return reflect.ValueOf(i), err
}
//else if .......增加其他一些类型的转换
return reflect.ValueOf(value), errors.New("未知的类型:" + ntype)
}
|