golang 实现两个结构体复制字段


Posted in Golang onApril 28, 2021

实际工作中可能会有这样的场景:

两个结构体(可能类型一样), 字段名和类型都一样, 想复制一个结构体的全部或者其中某几个字段的值到另一个(即merge操作),

自然想到可以用反射实现

package main
import "fmt"
import "reflect"
// 用b的所有字段覆盖a的
// 如果fields不为空, 表示用b的特定字段覆盖a的
// a应该为结构体指针
func CopyFields(a interface{}, b interface{}, fields ...string) (err error) {
	at := reflect.TypeOf(a)
	av := reflect.ValueOf(a)
	bt := reflect.TypeOf(b)
	bv := reflect.ValueOf(b)
	// 简单判断下
	if at.Kind() != reflect.Ptr {
		err = fmt.Errorf("a must be a struct pointer")
		return
	}
	av = reflect.ValueOf(av.Interface())
	// 要复制哪些字段
	_fields := make([]string, 0)
	if len(fields) > 0 {
		_fields = fields
	} else {
		for i := 0; i < bv.NumField(); i++ {
			_fields = append(_fields, bt.Field(i).Name)
		}
	}
	if len(_fields) == 0 {
		fmt.Println("no fields to copy")
		return
	}
	// 复制
	for i := 0; i < len(_fields); i++ {
		name := _fields[i]
		f := av.Elem().FieldByName(name)
		bValue := bv.FieldByName(name)
		// a中有同名的字段并且类型一致才复制
		if f.IsValid() && f.Kind() == bValue.Kind() {
			f.Set(bValue)
		} else {
			fmt.Printf("no such field or different kind, fieldName: %s\n", name)
		}
	}
	return
}
type S1 struct {
    Name string
    Age int
}
type S2 struct {
    Name string
    Age int32
}
func main() {
    s1 := S1{"hello", 22}
    s2 := S2{"world", 33}
    fmt.Println(s1, s2)
    CopyFields(&s1, s2)
    fmt.Println(s1, s2)
}

上述例子输出为:

{hello 22} {world 33}

no such field or different kind, fieldName: Age

{world 22} {world 33}

可见s2的Name字段值已经成功被覆盖.

而s2中Age字段和s1中Age字段类型不一样, 会忽略.

其实上面的还可以优化, 毕竟int32和int还是可以认为是"一样"的类型的,

不过思路就是这样.

补充:golang使用反射将一个结构体的数据直接复制到另一个结构体中(通过相同字段)

看代码吧~

package main
import (
	"fmt"
	"reflect"
)
type A struct {
	Name   string
	Gender string
	Age    int
}
type B struct {
	Name   string
	Gender string
}
//binding type interface 要修改的结构体
//value type interace 有数据的结构体
func structAssign(binding interface{}, value interface{}) {
	bVal := reflect.ValueOf(binding).Elem() //获取reflect.Type类型
	vVal := reflect.ValueOf(value).Elem()   //获取reflect.Type类型
	vTypeOfT := vVal.Type()
	for i := 0; i < vVal.NumField(); i++ {
		// 在要修改的结构体中查询有数据结构体中相同属性的字段,有则修改其值
		name := vTypeOfT.Field(i).Name
		if ok := bVal.FieldByName(name).IsValid(); ok {
			bVal.FieldByName(name).Set(reflect.ValueOf(vVal.Field(i).Interface()))
		}
	}
}
func main() {
	as := A{}
	bs := B{Name: "wfy", Gender: "男"}
	fmt.Println(as)
	structAssign(&as, &bs)
	fmt.Println(as)
}

以上为个人经验,希望能给大家一个参考,也希望大家多多支持三水点靠木。如有错误或未考虑完全的地方,望不吝赐教。

Golang 相关文章推荐
golang通过递归遍历生成树状结构的操作
Apr 28 Golang
Golang 如何实现函数的任意类型传参
Apr 29 Golang
Go标准容器之Ring的使用说明
May 05 Golang
go类型转换及与C的类型转换方式
May 05 Golang
Golang实现AES对称加密的过程详解
May 20 Golang
go web 预防跨站脚本的实现方式
Jun 11 Golang
手把手教你导入Go语言第三方库
Aug 04 Golang
Go Plugins插件的实现方式
Aug 07 Golang
Go 中的空白标识符下划线
Mar 25 Golang
Go语言 详解net的tcp服务
Apr 14 Golang
golang生成并解析JSON
Apr 14 Golang
Golang MatrixOne使用介绍和汇编语法
Apr 19 Golang
go结构体嵌套的切片数组操作
Apr 28 #Golang
golang json数组拼接的实例
Apr 28 #Golang
golang 实现对Map进行键值自定义排序
Apr 28 #Golang
go语言中json数据的读取和写出操作
Apr 28 #Golang
golang 实现菜单树的生成方式
Apr 28 #Golang
golang通过递归遍历生成树状结构的操作
Apr 28 #Golang
goland 恢复已更改文件的操作
You might like
PHP实现将视频转成MP4并获取视频预览图的方法
2015/03/12 PHP
yii2.0整合阿里云oss删除单个文件的方法
2017/09/19 PHP
根据地区不同显示时间的javascript代码
2007/08/13 Javascript
谷歌浏览器 insertCell与appendChild的区别
2009/02/12 Javascript
分享10篇优秀的jQuery幻灯片制作教程及应用案例
2011/04/16 Javascript
js中的getAttribute方法使用示例
2014/08/01 Javascript
Javascript中的包装类型介绍
2015/04/02 Javascript
jQuery原理系列-常用Dom操作详解
2016/06/07 Javascript
AngularJs学习第八篇 过滤器filter创建
2016/06/08 Javascript
使用vue制作FullPage页面滚动效果
2017/08/21 Javascript
nodejs 最新版安装npm 的使用详解
2018/01/18 NodeJs
Vue实现用户自定义字段显示数据的方法
2018/08/28 Javascript
iView框架问题整理小结
2018/10/16 Javascript
微信小程序rich-text富文本用法实例分析
2019/05/20 Javascript
使用VueCli3+TypeScript+Vuex一步步构建todoList的方法
2019/07/25 Javascript
vue项目中在可编辑div光标位置插入内容的实现代码
2020/01/07 Javascript
小程序卡片切换效果组件wxCardSwiper的实现
2020/02/13 Javascript
在Python中使用列表生成式的教程
2015/04/27 Python
python 多维切片之冒号和三个点的用法介绍
2018/04/19 Python
元组列表字典(莫烦python基础)
2019/04/03 Python
Django使用redis缓存服务器的实现代码示例
2019/04/28 Python
Python监控服务器实用工具psutil使用解析
2019/12/19 Python
python数据分析:关键字提取方式
2020/02/24 Python
PyTorch中的C++扩展实现
2020/04/02 Python
matlab、python中矩阵的互相导入导出方式
2020/06/01 Python
PyTorch的torch.cat用法
2020/06/28 Python
纯CSS3实现的井字棋游戏
2020/11/25 HTML / CSS
美的官方商城:Midea
2016/09/14 全球购物
免税水晶:Duty Free Crystal
2019/05/13 全球购物
宿舍标语大全
2014/06/19 职场文书
2014年底个人工作总结
2015/03/10 职场文书
化工厂员工工作总结
2015/10/15 职场文书
Python - 10行代码集2000张美女图
2021/05/23 Python
SpringBoot读取Resource下文件的4种方法
2021/07/02 Java/Android
使用Nginx搭载rtmp直播服务器的方法
2021/10/16 Servers
使用Mysql计算地址的经纬度距离和实时位置信息
2022/04/29 MySQL