为了账号安全,请及时绑定邮箱和手机立即绑定

如何在 Go 中保持强引用?

如何在 Go 中保持强引用?

Go
陪伴而非守候 2021-10-18 10:21:19
有什么办法可以在 Go 中保持强引用吗?鉴于以下令人费解的代码:package mainimport (  "fmt")func main() {     slice := make([]int, 5)  slice[3] = 25 // whatever index between 0 and 4 included I don't care  slicesArray := make([]*[]int, 2)    slicesArray[0] = &slice  fmt.Println((*(slicesArray[0]))[3])  slice = nil  fmt.Println((*(slicesArray[0]))[3])}当然,这程序崩溃,因为一旦设定切片到nil存储区为脏的垃圾收集器的标记。但是有没有办法告诉 Go 我的切片指针切片应该保持对这些切片的强引用?此外,保持对切片的引用而不是将 slicesArray 声明为是否有任何内存使用增益[][]int?是否有任何文档明确说明这应该如何工作?
查看完整描述

1 回答

?
哈士奇WWW

TA贡献1799条经验 获得超6个赞

您只需要复制切片值。切片类型的值是底层数组的描述符:


slice2 := slice

现在slice2将引用相同的共享底层数组,因此在slice归零后可以访问它。


长:


slice := make([]int, 5)

这将创建一个名为slicetype的局部变量[]int(并将使用一个描述符初始化,该描述符引用5在后台创建的大小数组make)。它是一个切片,它是在后台自动创建的底层数组的连续部分的描述符。


slicesArray[0] = &slice

这将局部变量(命名slice)的地址存储到 的第 0 个元素中slicesArray。请注意,这slicesArray只是一部分指针(哪些指针可能指向类型的值,[]int但现在无关紧要)。


所以仍然没有slice创建原始副本。


因此,当您将 type 的唯一值[]int(即名为 的局部变量slice)清零时,您将唯一的切片值清零(并且您将丢失对其支持数组的唯一引用)。


您想slice在清零后保留切片值吗?只需复制它(切片值)。复制切片类型的值只会复制描述符,不会复制后备数组;并且副本将引用相同的后备数组(它是共享的):


slice2 := slice // makes a copy of the slice value

slice = nil

在这之后*(slicesArray[0])仍然会指向一个切片值是nil,但我们有原始切片(和共享后备数组)的副本。


这样做:


slicesArray[0] = &slice2

fmt.Println((*(slicesArray[0]))[3])

将再次打印25。去游乐场


你应该保留切片值还是指向切片的指针?


由于切片只是相对较小的描述符,因此您应该保留并使用切片值。切片值已经包含对支持数组的“引用”。通过使用指向切片的指针添加另一个间接只会使事情复杂化并稍微减慢速度。切片已经被设计为小巧、高效和灵活(与 Go 中的“真实”数组相比)。


当然,在某些情况下,指向切片值的指针也可能很有用,例如,如果您想创建一个类似于内置append()函数的函数而不返回新切片。或者,当您创建一个其基础类型是切片类型的自定义类型时,您为该类型定义了修改切片值的方法(在这种情况下,指针接收器是必需的)。


查看完整回答
反对 回复 2021-10-18
  • 1 回答
  • 0 关注
  • 161 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信