【问题标题】:How the underlying array behaves in 'slice' in Golang底层数组如何在 Golang 的“切片”中表现
【发布时间】:2021-07-31 22:38:03
【问题描述】:

我对切片中的数组感到很困惑。代码贴在下面。

我知道 test() 从 main() 获取 arr 的副本,并且 test() 中的“附加”没有分配新数组,因为 cap > len。

但是,测试切片 arr[] 和主切片 arr[] 中的底层数组似乎不同,因为它们的地址不同。

另一方面,test() 中的“追加”操作确实修改了 main() 中的底层数组,因为在打印主切片的底层数组时会出现一个新的“1”。此外,test() 可以设置 arr[0] = 10,这在 main() 中可见。

这是怎么发生的?

slice中数组的地址取自这个post

func test(arr []int) {
    arr[0] = 10
    fmt.Printf("test slice - %p \n", &arr) //
    hdr := (*reflect.SliceHeader)(unsafe.Pointer(&arr))
    data := *(*[10]int)(unsafe.Pointer(hdr.Data))
    fmt.Printf("test - %p \n", &data)
    arr = append(arr, 1)
    fmt.Printf("test slice = %p \n", &arr) //
    hdr = (*reflect.SliceHeader)(unsafe.Pointer(&arr))
    data = *(*[10]int)(unsafe.Pointer(hdr.Data))
    fmt.Printf("test = %p \n", &data)
}

func main() {
    var arr []int = make([]int, 4, 10)
    hdr := (*reflect.SliceHeader)(unsafe.Pointer(&arr))
    data := *(*[10]int)(unsafe.Pointer(hdr.Data))
    fmt.Printf("main - %p \n", &data)
    test(arr)
    hdr = (*reflect.SliceHeader)(unsafe.Pointer(&arr))
    data = *(*[10]int)(unsafe.Pointer(hdr.Data))
    fmt.Printf("main = %p \n", &data)
    fmt.Println("main data ", data)
}

输出:

main - 0xc00009e050 
test slice - 0xc0000a6000 
test - 0xc00009e0a0 
test slice = 0xc0000a6000 
test = 0xc00009e0a0 
main = 0xc00009e050 
main data  [10 0 0 0 1 0 0 0 0 0]

【问题讨论】:

标签: arrays go memory-management append slice


【解决方案1】:

这个操作:

    data := *(*[10]int)(unsafe.Pointer(hdr.Data))

[10]int 数组复制到data。这里,data 是一个新数组,而不是切片的后备数组。

【讨论】:

  • @colm.anseo 看来我还要再等 4 分钟才能接受答案
猜你喜欢
  • 2016-08-10
  • 1970-01-01
  • 2016-03-29
  • 2018-12-13
  • 2019-12-16
  • 2018-02-05
  • 2019-10-04
  • 2014-08-13
  • 2013-04-12
相关资源
最近更新 更多