栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 面试经验 > 面试问答

在Go函数中返回局部数组的切片安全吗?

面试问答 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

在Go函数中返回局部数组的切片安全吗?

这在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
被认为是要在堆栈上分配的小数组。



转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/484326.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号