【发布时间】:2016-11-22 22:28:06
【问题描述】:
这是我在 Golang 的第一天,当我尝试它的切片操作时,比如append(),有一件事情让我很困惑:
package main
import "fmt"
func main() {
s := []int{2, 3, 5, 7, 11, 13}
a:= s[2:4];
a = append(a, 1000, 1001);
a[1] = 100;
printSlice("a:", a)
printSlice("s:", s)
}
func printSlice(title string, s []int) {
fmt.Printf("%s len=%d cap=%d %v\n", title, len(s), cap(s), s)
}
当我只将两个数字附加到 a 时,例如:
a = append(a, 1000, 1001);
...结果是:
a: len=4 cap=4 [5 100 1000 1001]
s: len=6 cap=6 [2 3 5 100 1000 1001]
我认为,a 显示为对 s 的引用。
但是当我将那行代码更改为:
a = append(a, 1000, 1001, 1002);
...结果变成:
a: len=5 cap=8 [5 100 1000 1001 1002]
s: len=6 cap=6 [2 3 5 7 11 13]
我认为,a 已重新分配给另一段内存,以保存整个内容,并分离对 s 的引用。
这太不一致了,让我很困惑,有时很容易犯这个错误(比如当你有一个随机数量的值要附加时)。
为什么 Golang 是这样设计的?如果我只想要 JavaScript 的 slice 和 push 中的操作,如何避免这种情况?
【问题讨论】:
-
我认为这个想法是你只是不
append来查看共享数据。如果你想获取一个子切片并附加到它,你制作一个副本。 -
只有在不理解切片背后的简单语义的情况下才会显得不一致。如果您不确定发生了什么,可以阅读大量资源:Go Slices: usage and internals、A Tour of Go: Slices、Slice Types 和 Appending any Copying Slices、Go By Example: Slices 和 Slice Tricks 的规范
-
@user2357112 谢谢,现在我明白了。
-
@JimB 谢谢,我会读到他们的。
标签: go