概念
golang开发时,我们会经常的把一个变量赋值给另一个变量,这个过程可能发生深拷贝也可能发生浅拷贝,二者有什么区别和联系呢?
1、深拷贝(Deep Copy)
深拷贝,拷贝的是数据本身,创造一个新对象,新创建的对象与原对象不共享内存,新创建的对象在内存中开辟一个新的内存地址,新对象值修改时不会影响原对象值。既然内存地址不同,释放内存地址时,可分别释放。
值类型的数据,默认全部都是深拷贝,Array、Int、String、Struct、Float,Bool。
package main
import (
"fmt"
)
func main() {
a := [3]int{1,2,3}
b := a //深拷贝
b[0] = 4 //修改数组b的值,不影响数组a
fmt.Println(a,b) //[1 2 3] [4 2 3]
}
2、浅拷贝(Shallow Copy)
浅拷贝,拷贝的是数据地址,只复制指向的对象的指针,此时新对象和老对象指向的内存地址是一样的,新对象值修改时老对象也会变化。释放内存地址时,同时释放内存地址。
引用类型的数据,默认全部都是浅拷贝,Slice,Map。
package main
import (
"fmt"
)
func main() {
a := []int{1,2,3} //定义一个切片
b := a //浅拷贝
b[0] = 4 //修改b的值,a的值也会跟着变
fmt.Println(a,b) //[4 2 3] [4 2 3]
//map同样也是浅拷贝
c := map[string]int {"柯南":98,"lufy":75,"naruto":86}
d := c
d["lufy"] = 88
fmt.Println(c,d) //map[lufy:88 naruto:86 柯南:98] map[lufy:88 naruto:86 柯南:98]
}
区别
深拷贝和浅拷贝的本质区别,在于是否真正获取(复制)对象实体,而不是仅仅引用。
扩容摆脱同根
从上述例子看出来,slice若不是深拷贝,或者重新生成新空间,无论通过参数传递还是使用 := 或者 [:]赋值都存在同根性。
而扩容可以摆脱这种同根性。
Slice与Array最大的区别在于Slice不需要指定大小会自动扩容等一些特性,Slice在多次append元素时,若满足扩容策略,这时候内部就会重新申请一块内存空间,将原本的元素拷贝一份到新的内存空间上。此时其与原本的数组就没有任何关联关系了,再进行修改值也不会变动到原始数组。
package main
import (
"fmt"
)
func main() {
a := []int{1,2,3} //定义一个切片
b := a[0:1]
for i:=0;i<=6;i++{
b = append(b,i) //容量未满时是浅拷贝,一旦扩容就是深拷贝了
}
b[0] = 10 //验证
fmt.Println(a,b) //[1 0 1] [10 0 1 2 3 4 5 6]
}
网友评论