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 interface判断为空nil的实现代码
Apr 24 Golang
golang正则之命名分组方式
Apr 25 Golang
Golang 实现超大文件读取的两种方法
Apr 27 Golang
go 原生http web 服务跨域restful api的写法介绍
Apr 27 Golang
golang 如何用反射reflect操作结构体
Apr 28 Golang
Go语言中break label与goto label的区别
Apr 28 Golang
解决Go gorm踩过的坑
Apr 30 Golang
Golang并发操作中常见的读写锁详析
Aug 30 Golang
golang生成vcf通讯录格式文件详情
Mar 25 Golang
golang三种设计模式之简单工厂、方法工厂和抽象工厂
Apr 10 Golang
Golang 切片(Slice)实现增删改查
Apr 22 Golang
Golang 实现WebSockets
Apr 24 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
模拟xcopy的函数
2006/10/09 PHP
利用PHP实现与ASP Banner组件相似的类
2006/10/09 PHP
手把手教你打印出PDF(关于fpdf的简单应用)
2013/06/25 PHP
php网页标题中文乱码的有效解决方法
2014/03/05 PHP
php常用字符串比较函数实例汇总
2014/11/24 PHP
android上传图片到PHP的过程详解
2015/08/03 PHP
PHP yield关键字功能与用法分析
2019/01/03 PHP
php实现将数组或对象写入到文件的方法小结【三种方法】
2020/04/22 PHP
phpcmsv9.0任意文件上传漏洞解析
2020/10/20 PHP
Jquery增加鼠标中间功能mousewheel的实例代码
2013/09/05 Javascript
自己使用js/jquery写的一个定制对话框控件
2014/05/02 Javascript
使用typeof判断function是否存在于上下文
2014/08/14 Javascript
Bootstrap3 datetimepicker控件使用实例
2016/12/13 Javascript
js控制按钮,防止频繁点击响应的实例
2017/02/15 Javascript
基于vue.js路由参数的实例讲解——简单易懂
2017/09/07 Javascript
jQuery实现点击下拉框中的值累加到文本框中的方法示例
2017/10/28 jQuery
JS交互点击WKWebView中的图片实现预览效果
2018/01/05 Javascript
jQuery实现模糊查询的方法分析
2018/05/10 jQuery
js 计算图片内点个数的示例代码
2019/04/04 Javascript
vue缓存的keepalive页面刷新数据的方法
2019/04/23 Javascript
jquery中为什么能用$操作
2019/06/18 jQuery
vue实现将一个数组内的相同数据进行合并
2019/11/07 Javascript
react-native 实现购物车滑动删除效果的示例代码
2021/01/15 Javascript
Python3读取zip文件信息的方法
2015/05/22 Python
python字符串中的单双引
2017/02/16 Python
Django如何配置mysql数据库
2018/05/04 Python
解决django前后端分离csrf验证的问题
2019/02/03 Python
django之从html页面表单获取输入的数据实例
2020/03/16 Python
Python urllib request模块发送请求实现过程解析
2020/12/10 Python
Paper Cape官网:美国婴儿和儿童服装品牌
2019/11/02 全球购物
药学专业学生的自我评价分享
2014/02/06 职场文书
2014年元旦活动方案
2014/02/15 职场文书
会计助理岗位职责
2014/02/17 职场文书
最新大学生创业计划书写作攻略
2014/04/02 职场文书
2014年学校德育工作总结
2014/12/05 职场文书
三十年同学聚会致辞
2015/07/28 职场文书