Golang深拷贝浅拷贝

在了解原型设计模式之前我们需要新知道Golang的深拷贝与浅拷贝之间的区别。

推荐大家新看看Slice 和 Map那么常见的坑:https://blog.csdn.net/weixin_40165163/article/details/90707593

github:https://github.com/zhumengyifang/GolangDesignPatterns

数据结构:

//速度速值
type Speed int//风扇转速
type FanSpeed struct {Speed Speed
}//售价
type Money struct {Length float64
}//内存数量以及大小
type Memory struct {Count      intMemorySize []int
}//电脑信息
type Computer struct {SystemName string              //系统名字UseNumber  int                 //使用次数Memory     Memory              //存储Fan        map[string]FanSpeed //风扇Money      Money               //售价
}

浅拷贝:

接触过 Java或者C#的同学应该知道浅拷贝对于值类型的话是完全拷贝一份,而对于引用类型是拷贝其地址。也就是拷贝的对象修改引用类型的变量同样会影响到源对象。

这里Golang同理,在上述测试类型中涉及到 Slice 和 Map的修改则会互相影响。

测试1:

func ComputerStart1() {Pc1 := Computer{SystemName: "Windows",UseNumber:  1000,Memory:     Memory{Count: 4, MemorySize: []int{32, 32, 32, 32}},Fan:        map[string]FanSpeed{"left": {2500}, "right": {2000}},Money:      Money{123.45},}//浅拷贝Pc2:=Pc1fmt.Printf("PcInfo Pc1:%v, Pc2:%v\n", Pc1, Pc2)//修改切片内容以及map信息影响Pc1Pc2.SystemName ="MacOs"Pc2.UseNumber =100Pc2.Memory.Count =2Pc2.Memory.MemorySize[0]=8Pc2.Memory.MemorySize[1]=8Pc2.Memory.MemorySize[2]=0Pc2.Memory.MemorySize[3]=0Pc2.Fan["left"]=FanSpeed{2000}Pc2.Fan["right"]=FanSpeed{1500}fmt.Printf("PcInfo Pc1:%v, Pc2:%v\n", Pc1, Pc2)
}

输入信息:

PcInfo Pc1:{Windows 1000 {4 [32 32 32 32]} map[left:{2500} right:{2000}] {123.45}}, Pc2:{Windows 1000 {4 [32 32 32 32]} map[left:{2500} right:{2000}] {123.45}}
PcInfo Pc1:{Windows 1000 {4 [8 8 0 0]} map[left:{2000} right:{1500}] {123.45}}, Pc2:{MacOs 100 {2 [8 8 0 0]} map[left:{2000} right:{1500}] {123.45}}

对于PC2的修改影响到了PC1的Slice 和 Map

测试2:

func ComputerStart2() {Pc1 := Computer{SystemName: "Windows",UseNumber:  1000,Memory:     Memory{Count: 4, MemorySize: []int{32, 32, 32, 32}},Fan:        map[string]FanSpeed{"left": {2500}, "right": {2000}},Money:      Money{123.45},}//浅拷贝Pc2:=Pc1fmt.Printf("PcInfo Pc1:%v, Pc2:%v\n", Pc1, Pc2)ModifyCat(Pc2)fmt.Printf("PcInfo Pc1:%v, Pc2:%v\n", Pc1, Pc2)
}func ModifyCat(pc Computer) {fmt.Printf("PcInfo Pc1:%v\n", pc)pc.SystemName ="MacOs"pc.UseNumber =100pc.Memory.Count =2pc.Memory.MemorySize[0]=8pc.Memory.MemorySize[1]=8pc.Memory.MemorySize[2]=0pc.Memory.MemorySize[3]=0pc.Fan["left"]=FanSpeed{2000}pc.Fan["right"]=FanSpeed{1500}fmt.Printf("PcInfo Pc1:%v\n", pc)
}

输入:

PcInfo Pc1:{Windows 1000 {4 [32 32 32 32]} map[left:{2500} right:{2000}] {123.45}}, Pc2:{Windows 1000 {4 [32 32 32 32]} map[left:{2500} right:{2000}] {123.45}}
PcInfo Pc1:{Windows 1000 {4 [32 32 32 32]} map[left:{2500} right:{2000}] {123.45}}
PcInfo Pc1:{MacOs 100 {2 [8 8 0 0]} map[left:{2000} right:{1500}] {123.45}}
PcInfo Pc1:{Windows 1000 {4 [8 8 0 0]} map[left:{2000} right:{1500}] {123.45}}, Pc2:{Windows 1000 {4 [8 8 0 0]} map[left:{2000} right:{1500}] {123.45}}

这里在方法中修改PC2同样影响到了 PC1以及PC2,是因为在Golang中方法中传递的参数同样被拷贝了一份,他们修改的Slice 和 Map都是同一份地址。

那么对于浅拷贝来说如何避免这种情况的发生呢?

测试3:

func ComputerStart2() {Pc1 := Computer{SystemName: "Windows",UseNumber:  1000,Memory:     Memory{Count: 4, MemorySize: []int{32, 32, 32, 32}},Fan:        map[string]FanSpeed{"left": {2500}, "right": {2000}},Money:      Money{123.45},}//浅拷贝Pc2:=Pc1fmt.Printf("PcInfo Pc1:%v, Pc2:%v\n", Pc1, Pc2)//切片以及map新空间互不影响Pc2.SystemName ="MacOs"Pc2.UseNumber =100Pc2.Memory =Memory{Count: 2, MemorySize: []int{8, 8}}Pc2.Fan =map[string]FanSpeed{"left": {2000}, "right": {1500}}Pc2.Money =Money{1000.45}fmt.Printf("PcInfo Pc1:%v, Pc2:%v\n", Pc1, Pc2)
}

输出:

PcInfo Pc1:{Windows 1000 {4 [32 32 32 32]} map[left:{2500} right:{2000}] {123.45}}, Pc2:{Windows 1000 {4 [32 32 32 32]} map[left:{2500} right:{2000}] {123.45}}
PcInfo Pc1:{Windows 1000 {4 [32 32 32 32]} map[left:{2500} right:{2000}] {123.45}}, Pc2:{MacOs 100 {2 [8 8]} map[left:{2000} right:{1500}] {1000.45}}

既然只有Slice 和 Map会受到影响我们这里重新给定地址重新生成一个Slice和Map就可以不受影响。

深拷贝

对于深拷贝就比较好了解了,任何对象都会被完完整整的拷贝一份,拷贝对象与被拷贝对象不存在如何联系,也就不会互相影响。如果你需要拷贝的对象中没有引用类型,那么对于Golang而言使用浅拷贝就可以了。

基于序列化和反序列化来实现对象的深度拷贝:

func deepCopy(dst, src interface{}) error {var buf bytes.Bufferif err := gob.NewEncoder(&buf).Encode(src); err != nil {return err}return gob.NewDecoder(bytes.NewBuffer(buf.Bytes())).Decode(dst)
}

需要深拷贝的变量必须首字母大写才可以被拷贝

测试1:

func ComputerStart4() {Pc1 := &Computer{SystemName: "Windows",UseNumber:  1000,Memory:     Memory{Count: 4, MemorySize: []int{32, 32, 32, 32}},Fan:        map[string]FanSpeed{"left": {2500}, "right": {2000}},Money:      Money{123.45},}//深拷贝Pc2:= new(Computer)if err:= deepCopy(Pc2,Pc1);err!=nil{panic(err.Error())}fmt.Printf("PcInfo Pc1:%v, Pc2:%v\n", Pc1, Pc2)ModifyCat1(*Pc2)fmt.Printf("PcInfo Pc1:%v, Pc2:%v\n", Pc1, Pc2)
}

输出:

PcInfo Pc1:&{Windows 1000 {4 [32 32 32 32]} map[left:{2500} right:{2000}] {123.45}}, Pc2:&{Windows 1000 {4 [32 32 32 32]} map[left:{2500} right:{2000}] {123.45}}
PcInfo Pc1:{Windows 1000 {4 [32 32 32 32]} map[left:{2500} right:{2000}] {123.45}}
PcInfo Pc1:{MacOs 100 {2 [8 8 0 0]} map[left:{2000} right:{1500}] {123.45}}
PcInfo Pc1:&{Windows 1000 {4 [32 32 32 32]} map[left:{2500} right:{2000}] {123.45}}, Pc2:&{Windows 1000 {4 [8 8 0 0]} map[left:{2000} right:{1500}] {123.45}}

可以看到PC2经过浅拷贝(参数传递)在修改Slice和Map受到影响的也只有PC2和PC2的浅拷贝对象。对于PC1没有任何影响。

下一章原型设计模式:https://blog.csdn.net/weixin_40165163/article/details/90671135

Golang深拷贝浅拷贝相关推荐

  1. java深拷贝和浅拷贝_Java 深拷贝浅拷贝 与 序列化

    一.浅拷贝.深拷贝 浅拷贝会对对象中的成员变量进行拷贝:如果是基本类型,拷贝的就是基本类型的值:如果属性是内存地址(引用类型),拷贝的就是内存地址 : 深拷贝,除了基本类型外,引用类型所引用的对象也会 ...

  2. Java基础 深拷贝浅拷贝

    Java基础 深拷贝浅拷贝 非基本数据类型 需要new新空间 class Student implements Cloneable{private int id;private String name ...

  3. 原型模式与深拷贝浅拷贝

    原型模式与深拷贝浅拷贝 原型模式 Java中的原型模式 简单的例子 浅拷贝 深拷贝 效率比较 JMH测试样例 测试结果 原型模式 用一个已经创建的实例作为原型,通过复制该原型对象来创建一个和原型相同或 ...

  4. Map的putAll方法踩坑实记(对象深拷贝浅拷贝)

    文章目录 问题描述 编写测试代码模拟问题场景 场景1:Map中不包含对象 场景2:Map中包含对象 什么是对象的浅拷贝深拷贝 如何实现深拷贝 问题描述 在一个产品管理系统中,产品信息需要封装一份同步业 ...

  5. 一篇文章彻底说清JS的深拷贝/浅拷贝

    一篇文章彻底说清JS的深拷贝and浅拷贝 这篇文章的受众 第一类,业务需要,急需知道如何深拷贝JS对象的开发者. 第二类,希望扎实JS基础,将来好去面试官前秀操作的好学者. 写给第一类读者 你只需要一 ...

  6. JavaScript学习笔记(五)--深拷贝浅拷贝

    如何区分深拷贝与浅拷贝,简单点来说,就是假设B复制了A,当修改A时,看B是否会发生变化,如果B也跟着变了,说明这是浅拷贝,拿人手短,如果B没变,那就是深拷贝,自食其力. 本篇文章中也会简单阐述到栈堆, ...

  7. C++析构函数与构造函数深拷贝浅拷贝(C++初学面向对象编程)

    文章目录 一.析构函数 二.C++默认生成的函数 三.构造与析构的调用顺序 四.构造函数的浅拷贝 五.构造函数的深拷贝 一.析构函数 1.析构函数的作用 对象消亡时,自动被调用,用来释放对象占用的内存 ...

  8. 浅谈C#深拷贝,浅拷贝

    1.深拷贝与浅拷贝 拷贝即是通常所说的复制(Copy)或克隆(Clone),对象的拷贝也就是从现有对象复制一个"一模一样"的新对象出来.虽然都是复制对象,但是不同的 复制方法,复制 ...

  9. 真深复制python_Python深复制浅复制or深拷贝浅拷贝

    简单点说 1. copy.copy 浅拷贝 只拷贝父对象,不会拷贝对象的内部的子对象. 2. copy.deepcopy 深拷贝 拷贝对象及其子对象 用一个简单的例子说明如下: >>> ...

  10. ES6中展开运算符的深拷贝浅拷贝理解(ElementUI表格点击编辑,模态框内容与表格数据一起变的问题)

    项目中遇到的问题: 在elementui中表格点击按钮传值的时候,通过bus中的$emit传对象,在弹出的模态框中用bus的$on接收对象,然后对传的对象进行改变,结果发现改变了原表格的数据. 然后就 ...

最新文章

  1. Gin 框架学习笔记(02)— 参数自动绑定到结构体
  2. 【SICP练习】30 练习1.36
  3. 解决ArcMap启动时只停留在初始化界面的方法
  4. python在中小学教学中的应用-中小学Python教学的几点建议
  5. python中%是什么意思_python中%代表什么意思?
  6. linux各版本代码量,linux各版本对应溢出漏洞总结(溢出代码)
  7. 计算bom的准确用量
  8. SON Web Token设计单点登录系统
  9. [ESC] EnTT 学习记录 2
  10. centos 6.5 yum mysql 5.6_centos 6.5 yum安装 mysql 5.6
  11. python2和python3中encoding的差别
  12. LINUX安装TensorRT及特别注意事项
  13. Ctrix-XenApp中误删应用服务器,如何重新添加
  14. BP神经网络代码和原理
  15. Redis 下载与安装(Windows版)
  16. 如何制作微信小程序(三个步骤开发小程序)
  17. java不想被gc,Java GC 必知必会
  18. 板岩 Steven Slate Audio :FG-2A 压缩评测
  19. Ubuntu大于2T硬盘,分区并挂载
  20. MicroPython ESP32 ADC(模拟量转数字量)示例

热门文章

  1. 谈谈业务系统的监控报警
  2. java 对音频文件降噪_如何对音频文件降噪?闪电音频剪辑软件为音频降噪的方法...
  3. 【题解】洛谷P1661扩散(同LibreOJ10015) 曼哈顿距离最小生成树
  4. 云流送技术可以支持多人交互吗?
  5. ACwing 149. 荷马史诗
  6. 《算法竞赛进阶指南》荷马史诗
  7. 8.6 百度首页编写-导航栏
  8. 【美团校招在线考试笔试题】钱币面值组合
  9. Python的Method理解
  10. gimp 抠图_GMIC(gimp 快速抠图)V1.5.2.4 免费版