前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Go语言中浅拷贝和深拷贝的区别是什么?

Go语言中浅拷贝和深拷贝的区别是什么?

作者头像
小锟哥哥
发布2022-05-10 09:07:56
2640
发布2022-05-10 09:07:56
举报
文章被收录于专栏:GoLang全栈

要想搞明白深拷贝和浅拷贝的区别,我们需要先弄懂以下几点:

一、值类型和引用类型

Go 语言里面变量有两类,一类是值类型,一类是引用类型。

两者区别是什么呢?

我们在电脑里面创建的变量,都是需要内存来存放的。

值变量就是直接,一个内存地址对应一个值。

而引用变量,则是某个值存放的是另一个值的地址。

我画了一个逻辑图,帮助我们去理解这个概念。

在 Go 语言中:

  • string、int、bool、float 等这些都属于值类型
  • slice、map、chan 等这些都属于引用类型

二、什么是浅拷贝和深拷贝?

而我们提到的深拷贝和浅拷贝,则指的是引用类型的值处理方案。

浅拷贝指的是,把变量里面存的内存地址拷贝了,所指向的真实值并没拷贝。

像下面这张图:

0x004 浅拷贝到了 0x003 里面,实际上只是拷贝了一个 0x006 这个内存地址。

代码是怎么实现的呢?

代码语言:javascript
复制
func main() {
 a := []string{"1","2","3"}
 b := a
 fmt.Println("a:",a)
 fmt.Println("b:",b)
}

//执行结果
$ go run cp.go 
a: [1 2 3]
b: [1 2 3]

怎么去证明是浅拷贝呢?

我们现在去改变下 a 切片里面的值:

代码语言:javascript
复制
func main() {
 a := []string{"1","2","3"}
 b := a
 a[0]="ko"
 fmt.Println("a:",a)
 fmt.Println("b:",b)
}
//执行结果
$ go run cp.go 
a: [ko 2 3]
b: [ko 2 3]

你会发现我改了 a 里面的值,b 里面的值同样被改了。

为什么会这样呢?

Go 的底层,slice 他其实是一个特殊的结构体,他包含三个字段:

代码语言:javascript
复制
// A notInHeapSlice is a slice backed by go:notinheap memory.
type notInHeapSlice struct {
 array *notInHeap
 len   int
 cap   int
}

这个数组里面的 array 才是真实数组值的存放地址。

三、如何实现深拷贝?

在 Go 里面我们只需要使用 copy 即可:

代码语言:javascript
复制
func main() {
 a := []string{"1","2","3"}
 // 初始化一个空数组
 b := make([]string,len(a),cap(a))
 copy(b, a)
 a[0]="ko"
 fmt.Println("a:",a)
 fmt.Println("b:",b)
}
//执行结果
$ go run cp.go 
a: [ko 2 3]
b: [1 2 3]

我们在初始化 b 数组的时候,我们需要指定数组的长度和容量,你可以直接 b := make([]string, 3) 但是我们并不建议这样去写。

这样我们创建出来的 b ,就是独立的一个数组切片了。

你学废了么?

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2022-02-23,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 GoLang全栈 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一、值类型和引用类型
  • 二、什么是浅拷贝和深拷贝?
    • 为什么会这样呢?
    • 三、如何实现深拷贝?
    领券
    问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档