go反射实现实体映射
时间:2020-05-06
本文章向大家介绍go反射实现实体映射,主要包括go反射实现实体映射使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
源码地址: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) }
运行结果如下:
原文地址:https://www.cnblogs.com/marshhu/p/12837834.html
- 来学习几个简单的Hive函数啦
- 推荐系统实战-基于用户的协同过滤
- 素数的筛法
- 听说GAN很高大上,其实就这么简单
- python3 解码base64遇到的问题与解决
- TensorFlow从0到1 - 16 - L2正则化对抗“过拟合”
- 使用虚拟环境,搭建python3+scrapy
- Matplotlib基础全攻略
- Python 小爬虫 - 爬取今日头条街拍美女图
- python3使用zookeeper和私钥解密及编码转化配置信息
- Python中os.path.dirname(__file__)的用法
- TensorFlow从0到1 - 18 - TensorFlow 1.3.0安装手记
- Python + Splinter 实现浏览器自动化操作入门指南
- 动态地理信息可视化——leaflet在线地图简介
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- 使用TypeScript积累自己的类库
- 在Egret项目中使用protobuf
- JavaScript原型与继承
- 当TKE遇上Coding, 业务如何实现快速迭
- cocos creator 1.x透明渐变效果实现
- Cocos Creator 2.x透明渐变效果实现
- Themeleaf通过ajax局部更新
- ubuntu下利用expect实现screen多窗口开机运行
- hetzner服务器购买和安装debian系统
- 安全通告 | Apache SkyWalking SQL注入漏洞安全风险公告(CVE-2020-13921)
- Cmd Markdown 迁移备份的流程
- PyTorch3:计算图torch.autograph
- spark shell 配置 Kryo 序列化
- Mac里捣腾Kerberos(一)
- Spark on K8S 访问 Kerberized HDFS