切片复制变异原始切片

Slice copy mutating original slice

有人可以帮助解释为什么这段代码会改变原始数组 a 的 Golang 内部结构吗?

func main() {
    a := []int{1,2,3,4}
    b := a
    b = append(b[0:1], b[2:]...)
    fmt.Println(b)
    fmt.Println(a)
}

输出:

[1 3 4]
[1 3 4 4]

我认为 b := a 会按值传递。提前致谢。

切片就是这样工作的。 slice只是一个指针(+size+capacity),实际数据存储在数组中。

复制切片时,不会复制底层数组。然后你最终得到两个指向同一个数组的切片。改变一个切片的值将通过另一个切片可见。

有关详细信息,请参阅 Go Slices: usage and internals

如果你想保持原来的切片不变,先做一个deep copy。比如像这样

    b := append([]int{}, a...)  // deep copy

(Live demo)

切片基本上是对数组的包装。切片没有自己的数据,它们只是保存对数组的引用。在您给定的代码中,您将 a 分配给 b 现在它们都指示相同的数组。因此,当您改变切片 b 时,切片 a 也会被改变。

您可以使用 copy 方法将元素从一个数组复制到另一个数组。

// copy returns the count of total copied elements
count := copy(b /*destination*/ , a /*source*/)

但请确保分配一个与源数组长度相同的数组。 示例如下:

func main() {
    a := []int{1,2,3,4}
    b := make([]int, len(a))

    _ = copy(b, a)

    a[0] = 2

    fmt.Println(b)
    fmt.Println(a)
}