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
Go缓冲channel和非缓冲channel的区别说明
Apr 25 Golang
golang 如何用反射reflect操作结构体
Apr 28 Golang
基于Go Int转string几种方式性能测试
Apr 28 Golang
解决Go gorm踩过的坑
Apr 30 Golang
goland设置颜色和字体的操作
May 05 Golang
golang中的并发和并行
May 08 Golang
Go中的条件语句Switch示例详解
Aug 23 Golang
Go 通过结构struct实现接口interface的问题
Oct 05 Golang
Golang中channel的原理解读(推荐)
Oct 16 Golang
Golang 字符串的常见操作
Apr 19 Golang
基于Python实现西西成语接龙小助手
Aug 05 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
CI框架常用函数封装实例
2016/11/21 PHP
yii2使用gridView实现下拉列表筛选数据
2017/04/10 PHP
js脚本学习 比较实用的基础
2006/09/07 Javascript
jQuery LigerUI 使用教程表格篇(1)
2012/01/18 Javascript
基于jquery的鼠标拖动效果代码
2012/05/30 Javascript
JS文本框不能输入空格验证方法
2013/03/19 Javascript
jquery插件bxslider用法实例分析
2015/04/16 Javascript
JavaScript中通过提示框跳转页面的方法
2016/02/14 Javascript
JavaScript-html标题滚动效果的简单实现
2016/09/08 Javascript
js仿支付宝多方框输入支付密码效果
2016/09/27 Javascript
vue2.0+ 从插件开发到npm发布的示例代码
2018/04/28 Javascript
基于vue2的canvas时钟倒计时组件步骤解析
2018/11/05 Javascript
使用puppeteer爬取网站并抓出404无效链接
2018/12/20 Javascript
Python实现提取谷歌音乐搜索结果的方法
2015/07/10 Python
Python用Pillow(PIL)进行简单的图像操作方法
2017/07/07 Python
浅谈tensorflow1.0 池化层(pooling)和全连接层(dense)
2018/04/27 Python
PyTorch 1.0 正式版已经发布了
2018/12/13 Python
Django框架文件上传与自定义图片上传路径、上传文件名操作分析
2019/05/10 Python
python numpy中cumsum的用法详解
2019/10/17 Python
基于matplotlib xticks用法详解
2020/04/16 Python
工程师必须了解的LRU缓存淘汰算法以及python实现过程
2020/10/15 Python
call在Python中改进数列的实例讲解
2020/12/09 Python
Python3使用Selenium获取session和token方法详解
2021/02/16 Python
CSS3实现文字描边的2种方法(小结)
2020/02/14 HTML / CSS
html5 worker 实例(二) 图片变换效果
2013/06/24 HTML / CSS
捷克钓鱼用品网上商店:Parys.cz
2018/06/15 全球购物
美国礼品卡交易网站:Cardpool
2018/08/27 全球购物
C#实现对任一张表的数据进行增,删,改,查要求,运用Webservice,体现出三层架构
2014/07/11 面试题
成功的餐厅经营创业计划书
2014/01/15 职场文书
宪法宣传周工作方案
2014/05/26 职场文书
社区精神文明建设汇报材料
2014/08/17 职场文书
小学教师个人工作总结2015
2015/04/20 职场文书
爱心募捐通知范文
2015/04/27 职场文书
2016抗战胜利71周年红领巾广播稿
2015/12/18 职场文书
php随机生成验证码,php随机生成数字,php随机生成数字加字母!
2021/04/01 PHP
开发者首先否认《遗弃》被取消的传言
2022/04/11 其他游戏