1、深拷贝(Deep Copy)
拷贝的是数据本身,创造一个样的新对象,新创建的对象与原对象不共享内存,新创建的对象在内存中开辟一个新的内存地址,新对象值修改时不会影响原对象值。既然内存地址不同,释放内存地址时,可分别释放。
值类型的数据,默认全部都是深复制,Array、Int、String、Struct、Float,Bool。
2、浅拷贝(Shallow Copy)
拷贝的是数据地址,只复制指向的对象的指针,此时新对象和老对象指向的内存地址是一样的,新对象值修改时老对象也会变化。释放内存地址时,同时释放内存地址。
引用类型的数据,默认全部都是浅复制,Slice,Map。
数据结构:
//速度速值
type Speed int
//风扇转速
type FanSpeed struct {
Speed Speed
}
//售价
type Money struct {
Length float64
}
//内存数量以及大小
type Memory struct {
Count int
MemorySize []int
}
//电脑信息
type Computer struct {
SystemName string //系统名字
UseNumber int //使用次数
Memory Memory //存储
Fan map[string]FanSpeed //风扇
Money Money //售价
}
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:=Pc1
fmt.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 =100
pc.Memory.Count =2
pc.Memory.MemorySize[0]=8
pc.Memory.MemorySize[1]=8
pc.Memory.MemorySize[2]=0
pc.Memory.MemorySize[3]=0
pc.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都是同一份地址。
参考:https://blog.csdn.net/weixin_40165163/article/details/90680466
地址相同,同根。
一、浅拷贝同根
func main() {
nums := [3]int{}
nums[0] = 1
fmt.Printf("nums: %v , len: %d, cap: %d\n", nums, len(nums), cap(nums))
dnums := nums[0:2]
dnums[0] = 5
fmt.Printf("nums: %v ,len: %d, cap: %d\n", nums, len(nums), cap(nums))
fmt.Printf("dnums: %v, len: %d, cap: %d\n", dnums, len(dnums), cap(dnums))
}
1、深拷贝(Deep Copy):
拷贝的是数据本身,创造一个样的新对象,新创建的对象与原对象不共享内存,新创建的对象在内存中开辟一个新的内存地址,新对象值修改时不会影响原对象值。既然内存地址不同,释放内存地址时,可分别释放。
值类型的数据,默认全部都是深复制,Array、Int、String、Struct、Float,Bool。
2、浅拷贝(Shallow Copy):
拷贝的是数据地址,只复制指向的对象的指针,此时新对象和老对象指向的内存地址是一样的,新对象值修改时老对象也会变化。释放内存地址时,同时释放内存地址。
引用类型的数据,默认全部都是浅复制,Slice,Map。
二、本质区别:
是否真正获取(复制)对象实体,而不是引用。
三、如何理解?
这里举个例子,比如P2复制了P1,修改P1属性的时候,观察P2的属性是否会产生变化
1、P2的属性变化了,说明这是浅拷贝,堆中内存还是同一个值。
p2=&p1 // 浅拷贝,p2为指针,p1和p2共用一个内存地址
2、P2的属性没变化,说明这是深拷贝,堆中内存是不同的值了。
p2=p1 // 深拷贝,生成两个内存地址
四、演示示例:
深拷贝示例:
package main
import (
"fmt"
)
// 定义一个Robot结构体
type Robot struct {
Name string
Color string
Model string
}
func main() {
fmt.Println("深拷贝 内容一样,改变其中一个对象的值时,另一个不会变化。")
robot1 := Robot{
Name: "小白-X型-V1.0",
Color: "白色",
Model: "小型",
}
robot2 := robot1
fmt.Printf("Robot 1:%s\t内存地址:%p \n", robot1, &robot1)
fmt.Printf("Robot 2:%s\t内存地址:%p \n", robot2, &robot2)
fmt.Println("修改Robot1的Name属性值")
robot1.Name = "小白-X型-V1.1"
fmt.Printf("Robot 1:%s\t内存地址:%p \n", robot1, &robot1)
fmt.Printf("Robot 2:%s\t内存地址:%p \n", robot2, &robot2)
}
运行结果:
深拷贝 内容一样,改变其中一个对象的值时,另一个不会变化。
Robot 1:{小白-X型-V1.0 白色 小型} 内存地址:0xc000072330
Robot 2:{小白-X型-V1.0 白色 小型} 内存地址:0xc000072360
修改Robot1的Name属性值
Robot 1:{小白-X型-V1.1 白色 小型} 内存地址:0xc000072330
Robot 2:{小白-X型-V1.0 白色 小型} 内存地址:0xc000072360
深拷贝中,我们可以看到Robot1号的地址与Robot2号的内存地址是不同的,修改Robot1号的Name属性时,Robot2号不会变化。
浅拷贝我们用两种方式来介绍。
参考:
https://blog.csdn.net/alen_xiaoxin/article/details/124913809
https://blog.csdn.net/weixin_40165163/article/details/90680466
https://blog.csdn.net/weixin_40165163/article/details/90707593
标签:对象,32,fmt,Pc1,go,拷贝,内存地址 From: https://www.cnblogs.com/rebrobot/p/17252680.html