复制变量

时间:2016-11-23 10:52:47

标签: arrays pointers go slice

我想探讨一下当我们尝试复制变量时如何分配内存。我做了一些测试,这个让我困惑:

func testArrayAddress() {
    var a [3]int
    b := a
    fmt.Printf("address of a %p and of b %p \n", &(a[0]), &(b[0]))
}

输出结果为:

address of a 0xc8200126e0 and of b 0xc820012700

然而,我假设a和b并指向同一个数组,所以第一个元素的起始地址应该相同?

这让我怀疑当我们执行陈述b := a时发生了什么?最初我以为它会在我们初始化变量a时为数组分配一个内存块,而b := a使b指向同一个内存位置,但是它无法解释为什么地址第一个元素的不一样(应该是相同的元素)。

我更改了第一行代码:

func testArrayAddress() {
    var a = []int{1, 2, 3}
    b := a
    fmt.Printf("address of a's first element %p and of b %p \n", &(a[0]), &(b[0]))
}

然后输出是:

address of a's first element 0xc8200126e0 and of b 0xc8200126e0

现在它给了我相同的结果。

我想问的问题是:

  1. 在Golang中进行变量复制(b := a)时,我们是否还在内存中创建数据副本?对于不可变类型和可变类型都是一样的吗?

  2. 如果我们也在复制可变类型(例如数组),它如何设法实现修改变量也会影响其他人(a[0] = 42会影响b[0])?

  3. []int的类型与我在上一个案例中测试过的[number]int类型有什么不同?

1 个答案:

答案 0 :(得分:5)

[3]intarray[]intslice

数组表示其所有元素,在传递或分配时,所有元素都将被复制。

切片是一种类似于结构的小描述符,指向底层数组的一个连续部分。传递或分配时,只复制此标头(包括指针),因此“新”切片将指向相同的后备阵列。

回答您的确切问题:

  1. 是的,如果b := a是一个数组,则a会复制所有元素,但如果a是一个切片,则只复制标题。只要只有1个goroutine访问(修改)a,两者都是安全的,如果多个goroutine可以修改它们,则没有一个是安全的。

  2. 如果复制了一个数组,它将完全独立于“原始”,修改副本将对原始数据没有影响。如果复制了切片,则副本将指向存储元素的相同后备阵列。如果通过复制切片修改元素,则修改唯一元素,因此通过原始切片检查它,您只需检查元素的唯一“实例”(并观察修改后的值)。

  3. 这是第一句话:[]int是一个切片,[n]int是一个数组。

  4. 查看相关问题:

    Why have arrays in Go?
    Golang passing arrays to the function and modifying it

    阅读以下博客文章,了解有关切片和数组的更多详细信息:

    Go Slices: usage and internals
    Arrays, slices (and strings): The mechanics of 'append'