标签:for 广州 func dna user string ret com 内容
源码地址:https://github.com/marshhu/ma-tools
项目中经常要用到实体映射,以前做.net是用AutoMapper做的实体映射,感觉挺方便的。
然而最近做的golang项目,还是比较原始的手动赋值,弄起来挺痛苦的,实在受不了,动手写了个简单的实体映射工具方法,代码如下:
func MapTo(src interface{}, dst interface{}) error { srcType, srcValue := reflect.TypeOf(src), reflect.ValueOf(src) dstType, dstValue := reflect.TypeOf(dst), reflect.ValueOf(dst) //如果src是指针 if srcType.Kind() == reflect.Ptr { srcType, srcValue = srcType.Elem(), srcValue.Elem() // 取具体内容 } if dstValue.Kind() != reflect.Ptr || dstValue.IsNil() { return errors.New("dst is not a pointer or is nil") } dstType, dstValue = dstType.Elem(), dstValue.Elem() switch srcType.Kind() { case reflect.Struct: //结构体 item := reflect.New(dstValue.Type()) setValue(srcValue, item) if dstValue.CanSet() { dstValue.Set(item.Elem()) } case reflect.Slice: //切片 if dstType.Kind() != reflect.Slice { //fmt.Println(dstType.Kind()) return errors.New("dst type should be a slice") } for i := 0; i < srcValue.Len(); i++ { //fmt.Println(srcValue.Index(i)) item := reflect.New(dstValue.Type().Elem()) setValue(srcValue.Index(i), item) if dstValue.CanSet() { dstValue.Set(reflect.Append(dstValue, item.Elem())) } } case reflect.Array: //数组 if dstType.Kind() != reflect.Slice && dstType.Kind() != reflect.Array { //fmt.Println(dstType.Kind()) return errors.New("dst type should be a slice or a array") } if dstType.Kind() == reflect.Array { if dstValue.Len() < srcValue.Len() { return errors.New("dst array length should grater then src") } for i := 0; i < srcValue.Len(); i++ { fmt.Println(srcValue.Index(i)) item := reflect.New(dstValue.Type().Elem()) setValue(srcValue.Index(i), item) if dstValue.Index(i).CanSet() { dstValue.Index(i).Set(item.Elem()) } } } if dstType.Kind() == reflect.Slice { for i := 0; i < srcValue.Len(); i++ { //fmt.Println(srcValue.Index(i)) item := reflect.New(dstValue.Type().Elem()) setValue(srcValue.Index(i), item) if dstValue.CanSet() { dstValue.Set(reflect.Append(dstValue, item.Elem())) } } } case reflect.Map: //map if dstType.Kind() != reflect.Map { //源数据为切片,要求目标也为map return errors.New("dst type should be a map") } for _, key := range srcValue.MapKeys() { //fmt.Println(srcValue.MapIndex(key)) item := reflect.New(dstValue.Type()) setValue(srcValue.MapIndex(key), item) dstValue.SetMapIndex(key, srcValue.MapIndex(key)) } default: panic(fmt.Sprintf("%v cannot mapping", srcType.Kind())) } return nil } func setValue(srcValue reflect.Value, dstValue reflect.Value) error { if dstValue.Kind() != reflect.Ptr || dstValue.IsNil() { return errors.New("dst is not a pointer or is nil") } dstType, dstValue := dstValue.Type().Elem(), dstValue.Elem() if srcValue.Kind() == reflect.Struct { if dstValue.Kind() != reflect.Struct { return errors.New("dst type should be a struct pointer") } for i := 0; i < dstValue.NumField(); i++ { fieldInfo := dstType.Field(i) fieldName := fieldInfo.Name value := srcValue.FieldByName(fieldName) if !value.IsValid() || value.Kind() != fieldInfo.Type.Kind() { continue } if value.Kind() == reflect.Struct { item := reflect.New(dstValue.Field(i).Type()) setValue(value, item) if dstValue.Field(i).CanSet() { dstValue.Field(i).Set(item.Elem()) } } else { if dstValue.Field(i).IsValid() && dstValue.Field(i).CanSet() { dstValue.Field(i).Set(value) } } } } else { if dstValue.CanSet() { dstValue.Set(srcValue) } } return nil }
测试代码:
func main() { type Address struct { Country string City string } type AddressB struct { Country string } type User struct { ID int Name string Gender int Tel string Address Address } type UserDto struct { ID int Name string Avatar string Address AddressB } user := User{1, "小明", 1, "18800188001", Address{"中国", "深圳"}} fmt.Printf("user:%v\n", user) userDto := &UserDto{} err := mapping.MapTo(user, userDto) if err != nil { fmt.Println(err.Error()) } fmt.Printf("userDto:%v\n", userDto) users := []User{ {1, "小明", 1, "18800188001", Address{"中国", "深圳"}}, {2, "小红", 0, "18800188002", Address{"中国", "广州"}}, {3, "小李", 0, "18800188003", Address{"中国", "武汉"}}, {4, "小张", 1, "18800188004", Address{"中国", "北京"}}, } fmt.Printf("users:%v\n", users) var userDtos []UserDto err = mapping.MapTo(users, &userDtos) if err != nil { fmt.Println(err.Error()) } fmt.Printf("userDtos:%v\n", userDtos) }
运行结果如下:
标签:for 广州 func dna user string ret com 内容
原文地址:https://www.cnblogs.com/marshhu/p/12837834.html