arrays - 谁能解释这种附加到 golang slice 的奇怪行为

标签 arrays go slice

下面的程序有意外的输出。

func main(){
    s:=[]int{5}
    s=append(s,7)
    s=append(s,9)
    x:=append(s,11)
    y:=append(s,12)
    fmt.Println(s,x,y)
}

输出:[5 7 9] [5 7 9 12] [5 7 9 12]

为什么x的最后一个元素是12

最佳答案

slice 只是数组部分的一个窗口,它没有特定的存储空间。

这意味着如果数组的同一部分有两个 slice ,则两个 slice 必须“包含”相同的值。

这正是这里发生的事情:

  1. 当您执行第一个 append 时,您会在大小为 2 的基础数组上获得一个大小为 2 的新 slice 。
  2. 当您执行下一个 append 时,您会得到一个大小为 3 的新 slice ,但底层数组的大小为 4(append 通常分配比立即需要的空间更多的空间,因此它不需要在每次追加时分配)。
  3. 这意味着下一个 append 不需要新数组。所以 xy 都将使用与前面 slice s 相同的底层数组。你在这个数组的同一个槽中编写 11 然后 12,即使你得到两个不同的 slice (记住,它们只是窗口)。

您可以通过在每次追加后打印 slice 的容量来检查:

fmt.Println(cap(s))

如果你想在 xy 中有不同的值,你应该做一个 copy ,例如像这样:

s := []int{5}
s = append(s, 7)
s = append(s, 9)
x := make([]int,len(s))
copy(x,s)
x = append(x, 11)
y := append(s, 12)
fmt.Println(s, x, y)

这里的另一种解决方案可能是强制 s slice 后面的数组的容量不大于所需的容量(从而确保以下两个 append < em>必须使用新数组):

s := []int{5}
s = append(s, 7)
s = append(s, 9)
s = s[0:len(s):len(s)]
x := append(s, 11)
y := append(s, 12)
fmt.Println(s, x, y)

另见 Re-slicing slices in Golang

关于arrays - 谁能解释这种附加到 golang slice 的奇怪行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27568213/

相关文章:

php - 将 SQL 查询的数据返回到数组中

javascript - 通过 POST 将 JavaScript 数组发送到 PHP

go - 在 Golang 中将值从一个结构复制到另一个结构

arrays - []json.Rawmessage 是什么意思

python - 在 pandas 中,向数据帧的子集添加时间偏移量没有任何效果

ruby-on-rails - 如何定义包含反斜杠 ("\") 字符的 ruby​​ 数组?

javascript - 我不明白数组是如何工作的

Golang测试挂

go - 在 Kubernetes 中,Go 容器是否会在另一个容器使用内核时使用所有内核

recursion - 尝试将 slice 作为参数传递给递归函数时 slice 超出范围 (Go)