【Go】深拷贝与浅拷贝

导读:本篇文章讲解 【Go】深拷贝与浅拷贝,希望对大家有帮助,欢迎收藏,转发!站点地址:www.bmabk.com


一、深浅拷贝

在很多编程语言都有深浅拷贝的这个概念,当然golang也不例外。

在 go 语言中 值类型 赋值都是 深拷贝引用类型 一般都是 浅拷贝

其本质就是,深拷贝会拷贝数据(两变量存储地址不同,拷贝结束互不影响)。而浅拷贝只会拷贝内存的地址(即使拷贝结束,还是互相影响),所以就会出现,像 slice 那样修改底层数组的值,slice 的值也跟着改动。


二、深拷贝

b 拷贝 a 后,如果修改 a 的值,b不变,说明是值的拷贝,也就是深拷贝。

package main

import (
	"fmt"
)

func main() {
	var a = 123
	b := a    //值的拷贝,深拷贝
	fmt.Println(a, b)
	a = 456
	fmt.Println(a, b)
}

输出结果:

123 123
456 123

三、浅拷贝

b 拷贝 a 后,修改 a 的值,b 的值也跟着修改了;修改 b 的值,a 的值也跟着修改了。那就是地址的拷贝,是浅拷贝。

如下,a、b 两个 slice 指向同一个内存地址,slice 拷贝是浅拷贝。本质是因为 slice 属于 Go 的引用类型。

package main

import (
	"fmt"
)

func main() {
	a := []int{1, 2, 3}
	b := a //地址的拷贝,浅拷贝
	fmt.Println(a, b)

	a[0] = 1000
	fmt.Println(a, b)

	b[2] = 4000
	fmt.Println(a, b)
}

输出结果:

[1 2 3] [1 2 3]
[1000 2 3] [1000 2 3]
[1000 2 4000] [1000 2 4000]

实现 slice 深拷贝:

1.make 一个新的,然后使用 append 赋值:

package main

import (
	"fmt"
)

func main() {
	a := []int{1, 2, 3}
	b := make([]int, 0)     //创建新切片
	b = append(b, a[:]...)
	fmt.Println(a, b)
	a[1] = 1000
	fmt.Println(a, b)
	fmt.Printf("%p,%p", a, b)  // make 的新 b 和 a 拥有不同的地址
}

输出结果:

[1 2 3] [1 2 3]
[1 1000 3] [1 2 3]
0xc00000e270,0xc00000e288  

1.也可以通过内置的 copy 函数进行复制

需要注意的是copy函数不会扩容,也就是要复制的 slice 比原 slice 要大的时候,只会移除多余的。

package main

import (
	"fmt"
)

func main() {
	slice1 := []int{1, 2, 3, 4, 5}
	slice2 := []int{5, 4, 3}

	copy(slice2, slice1) // 只会复制slice1的前3个元素到slice2中
	fmt.Println(slice1, slice2)

	slice2 = []int{5, 4, 3}
	copy(slice1, slice2) // 只会复制slice2的3个元素到slice1的前3个位置
	fmt.Println(slice1, slice2)
}

输出结果:

[1 2 3 4 5] [1 2 3]
[5 4 3 4 5] [5 4 3]

四、总结

归根结底,使用 := 进行拷贝时:

1. 会产生深拷贝还是浅拷贝取决于被拷贝数据的数据类型:

  • 如果是值类型,就会产生深拷贝
  • 如果是引用类型,就会产生浅拷贝

关于 Go 的常用数据类型是值类型还是引用类型请参见我的另一篇文章:【Go】Go语言数据类型

2. 深浅拷贝的区别:

  • 深拷贝:光拷贝值,地址不相关。拷贝结束两变量互不影响。
  • 浅拷贝:拷贝地址。两变量指向同一地址。拷贝结束也相关,改变一个,另一个也跟着变。

3. 另外,对于引用类型,想实现深拷贝,就不能直接 := ,而是要先 new ,再赋值。


参考链接

  1. golang深浅拷贝

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/118980.html

(0)
seven_的头像seven_bm

相关推荐

发表回复

登录后才能评论
极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!