duanpi7578 2015-06-16 19:13
浏览 33
已采纳

如何在Go中保持强大的参考力?

Is there any way I can keep a strong reference in Go?

Given the following convoluted piece of code:

package main

import (
  "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])
}

This program of course crashes because once setting the slice to nil the garbage collector marks the memory area as dirty.

But is there a way to tell Go that my slice of pointers to slices should keep a strong reference to those slices? Also, is there any memory usage gain in keeping references to slices rather than declaring slicesArray as [][]int? Is there any doc clearly stating how this is supposed to work?

  • 写回答

1条回答 默认 最新

  • dousong9729 2015-06-16 19:24
    关注

    TL;DR: (summary)

    You just need to make a copy of the slice value. A value of slice type is a descriptor to an underlying array:

    slice2 := slice
    

    Now slice2 will refer to the same, shared underlying array and so it will be reachable after slice is zerored.

    In long:

    slice := make([]int, 5)
    

    This creates a local variable named slice of type []int (and will be initialized with a descriptor referring to an array of size 5 created in the background by make). It's a slice which is a descriptor to a contiguous part of an underlying array which is created automatically in the background.

    slicesArray[0] = &slice
    

    This stores the address of the local variable (named slice) into the 0th element of slicesArray. Note that slicesArray is just a slice of pointers (which pointers may point to values of type []int but that doesn't matter now).

    So still no copy of the original slice is created.

    And so when you zero the only value of type []int (which is the local variable named slice), you zero the only slice value (and you'll lose the only reference to its backing array).

    You want to keep the slice value after slice has been zeroed? Just make a copy of it (of the slice value). Copying a value of slice type only makes a copy of the descriptor, the backing array is not copied; and the copy will refer to the same backing array (it's shared):

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

    After this *(slicesArray[0]) will still point to a slice value being nil, but we have a copy of the original slice (and the shared backing array).

    So doing:

    slicesArray[0] = &slice2
    fmt.Println((*(slicesArray[0]))[3])
    

    Will print again 25. Go Playground

    Should you keep slice values or pointers to slices?

    Since slices are just descriptors which are relatively small, you should keep and work with slice values. A slice value already contains a "reference" to a backing array. Adding another indirection by using a pointer to a slice just complicates and slightly slows things down. A slice is already designed to be small, efficient and flexible (compared to "real" arrays in Go).

    Of course a pointer to a slice value may also be useful in some cases, for example if you would ever want to create a function similar to the builtin append() function without returning the new slice. Or when you create a custom type whose underlying type is a slice type, and you define methods for this type which modify the slice value (in this case a pointer receiver is necessary).

    Further readings: (the docs explaining everything in detail)

    Go Slices: usage and internals

    Arrays, slices (and strings): The mechanics of 'append'

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥50 potsgresql15备份问题
  • ¥15 Mac系统vs code使用phpstudy如何配置debug来调试php
  • ¥15 目前主流的音乐软件,像网易云音乐,QQ音乐他们的前端和后台部分是用的什么技术实现的?求解!
  • ¥60 pb数据库修改与连接
  • ¥15 spss统计中二分类变量和有序变量的相关性分析可以用kendall相关分析吗?
  • ¥15 拟通过pc下指令到安卓系统,如果追求响应速度,尽可能无延迟,是不是用安卓模拟器会优于实体的安卓手机?如果是,可以快多少毫秒?
  • ¥20 神经网络Sequential name=sequential, built=False
  • ¥16 Qphython 用xlrd读取excel报错
  • ¥15 单片机学习顺序问题!!
  • ¥15 ikuai客户端多拨vpn,重启总是有个别重拨不上