需求示例代码
type Student struct {
Name *string `db:"name"`
Age int64 `db:"age"`
}
value := map[string]interface{} {"name": "zhangsan", "age": 10}
需要通过上述的value来获得一个对应的Student对象。
func Copy(data map[string]interface{}, target interface{}) {
_value := reflect.ValueOf(target).Elem()
_type := reflect.TypeOf(target).Elem()
// 完成tag到域索引的映射
nameMap := make(map[string]int)
for i := 0; i < _value.NumField(); i++ {
nameMap[_type.Field(i).Tag.Get("db")] = i
}
for key, value := range data {
if idx, ok := nameMap[key]; ok {
// 检测变量类型,要判断struct属性的类型,是否是指针
if _value.Field(idx).Kind() == reflect.Ptr &&
_type.Field(idx).Type.String() == "*"+reflect.TypeOf(value).String() {
switch value.(type) {
case int:
tmpVal := value.(int)
_value.Field(idx).Set(reflect.ValueOf(&tmpVal))
case int32:
tmpVal := value.(int32)
_value.Field(idx).Set(reflect.ValueOf(&tmpVal))
case int64:
tmpVal := value.(int64)
_value.Field(idx).Set(reflect.ValueOf(&tmpVal))
case string:
tmpVal := value.(string)
_value.Field(idx).Set(reflect.ValueOf(&tmpVal))
case bool:
tmpVal := value.(bool)
_value.Field(idx).Set(reflect.ValueOf(&tmpVal))
case float64:
tmpVal := value.(float64)
_value.Field(idx).Set(reflect.ValueOf(&tmpVal))
default:
// 可用于确定未添加的参数,也可以是一个log,后面可以再通过log补上基本类型
panic(errors.New(fmt.Sprintf("未知基本类型%T\n", value)))
}
} else if _type.Field(idx).Type.String() == reflect.TypeOf(value).String() {
_value.Field(idx).Set(reflect.ValueOf(value))
} else {
// 可用于确定未添加的参数,也可以是一个log,然后最后再添加上
panic(errors.New(fmt.Sprintf("key「%v」value %v」; type 「%v」 => 「%v」\n",
key,
value,
reflect.TypeOf(value).String(),
_type.Field(idx).Type.String())))
}
}
}
}
正常赋值的操作
b := map[string]interface{}{"name": "zhangsan", "age": int64(10)}
student := new(Student)
Copy(b, student)