首页 >后端开发 >Golang >为什么在 Go 中附加到切片副本有时会修改原始数据?

为什么在 Go 中附加到切片副本有时会修改原始数据?

DDD
DDD原创
2024-12-01 12:15:13449浏览

Why Does Appending to a Slice Copy in Go Sometimes Modify the Original?

为什么 Go 中切片追加会修改原始切片?

Go 中内置的追加函数通过创建一个新的底层数组来将元素追加到切片中,复制现有元素,并附加新元素。如果原始切片和追加函数中使用的切片共享相同的底层数组,则对任一切片所做的更改将反映在两个切片中。

考虑以下代码片段:

func someFunc(A []int) int {
    ...
    tempA := A // copy the slice by value
    ...
    newArr = remove(tempA, i)
    ...
}

func remove(slice []int, s int) []int {
    return append(slice[:s], slice[s+1:]...)
}

这里,someFunc 函数接受一个切片 A 并创建它的一个副本,称为 tempA。然后,remove 函数对 tempA 执行追加函数,以删除索引 s 处的元素。

由于 tempA 切片最初引用与 A 相同的底层数组,因此对 tempA 所做的修改(通过追加函数)也将被删除。反映在A中。这是因为append函数创建了一个新的底层数组并将现有元素复制到其中。由于 A 和 tempA 共享相同的底层数组,因此对其中一个所做的任何更改也会传播到另一个。

由于切片的内部实现方式,这种行为在 Go 中是预期的:

  • 切片是描述底层数组的一部分的标头对象。
  • 复制切片时,标头被复制,但底层数组被复制不是。
  • 如果两个切片共享相同的标头,则它们引用相同的底层数组,并且对一个切片所做的修改会影响另一个切片。

要避免这种共享引用行为,您可以创建一个新切片并显式复制元素,如下所示:

tempA := make([]int, len(A))
copy(tempA, A)

以上是为什么在 Go 中附加到切片副本有时会修改原始数据?的详细内容。更多信息请关注PHP中文网其他相关文章!

声明:
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn