这在Spec:Slice
expressions中有详细说明。
不会复制该数组,但slice表达式的结果将是引用该数组的slice。在Go中,从函数或方法返回局部变量或它们的地址是绝对安全的,Go编译器执行逸出分析以确定值是否可以逸出该函数,以及是否可以逸出(或是否不能证明某个值)可能无法转义),它会在堆上分配它,因此函数返回后将可用。
切片表达式:
tmp[:end]意思是
tmp[0:end](因为缺少的
low索引默认为零)。既然你没有指定容量,则默认为
len(tmp) -0这是
len(tmp)这是
100。
您还可以使用 完整切片表达式 来控制结果切片的容量,该 表达式 的形式为:
a[low : high : max]
将结果切片的容量设置为
max - low。
更多示例来阐明所得切片的长度和容量:
var a [100]ints := a[:]fmt.Println(len(s), cap(s)) // 100 100s = a[:50]fmt.Println(len(s), cap(s)) // 50 100s = a[10:50]fmt.Println(len(s), cap(s)) // 40 90s = a[10:]fmt.Println(len(s), cap(s)) // 90 90s = a[0:50:70]fmt.Println(len(s), cap(s)) // 50 70s = a[10:50:70]fmt.Println(len(s), cap(s)) // 40 60s = a[:50:70]fmt.Println(len(s), cap(s)) // 50 70
在Go Playground上尝试一下。
避免堆分配
如果要在堆栈上分配它,则不能返回任何指向它(或其一部分)的值。如果将其分配在堆栈上,将无法保证返回后仍保持可用状态。
一种可能的解决方案是将指向数组的指针作为函数的参数传递(并且您可以返回一个切片,指定该函数填充的 有用 部分),例如:
func foo(tmp *[100]uint64) []uint64 { // ... return tmp[:end]}如果调用者函数在堆栈上创建了数组,则不会导致“重新分配”或“移动”到堆:
func main() { var tmp [100]uint64 foo(&tmp)}运行
go run -gcflags '-m -l' play.go,结果是:
./play.go:8: leaking param: tmp to result ~r1 level=0./play.go:5: main &tmp does not escape
该变量
tmp不会移到堆。
请注意,这
[100]uint64被认为是要在堆栈上分配的小数组。



