一架梯子,一头程序猿,仰望星空!
Golang高级特性面试题 > 内容正文

介绍下Go 语言中的深拷贝和浅拷贝


问题简答

通常在变量赋值、参数传递、函数返回值过程中产生变量拷贝,在变量拷贝过程中拷贝的是数据(值),还是存储数据的地址(引用)就是深拷贝(拷贝值)和浅拷贝(拷贝引用)的区别。

问题详解:

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

本质就是,深拷贝会拷贝数据(两个变量存储地址不同,拷贝结束互不影响)。而浅拷贝只会拷贝内存的地址(即使拷贝结束,还是互相影响)。

提示:浅拷贝效率比较高,深拷贝,如果变量数据比较大的话,复制数据需要消耗的时间越多。

深拷贝(又叫值传递)

例子:

package main

import (
    "fmt"
)

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

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

浅拷贝(又叫引用传递)

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]