当前位置: 首页 > 知识库问答 >
问题:

在Golang的“切片”中底层数组的行为

濮书
2023-03-14

我对切片中的数组感到非常困惑。代码发布在下面。

我知道test()从main()获取arr的副本,test()中的“append”不会分配新数组,因为cap

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

另一方面,test()中的append操作会修改main()中的基础数组,因为在打印主切片的基础数组时会出现一个新的1。此外,test()能够设置arr[0]=10,这在main()中可见。

这是怎么发生的?

切片中数组的地址取自本文。

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]

共有1个答案

哈朗
2023-03-14

此操作:

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

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

 类似资料:
  • 问题内容: 我是Go的新手,正在尝试编写一个读取RPM文件的应用程序。每个块的开头都有的魔术字符。 这是我的结构 我正在尝试执行以下操作: 我在网上搜索,不确定如何从切片到数组(不进行复制)。我总是可以制作魔术(甚至是),但我对如何从类型转换为更好奇? 问题答案: 内置方法 copy 只会将一个切片复制到一个切片,而不是将切片复制到一个数组。 您必须欺骗 复制 以将数组视为切片 或使用for循环进

  • 切片包含三个组件:长度、容量和指向底层数组的指针。 当我们尝试将

  • 本文向大家介绍理解Golang中的数组(array)、切片(slice)和map,包括了理解Golang中的数组(array)、切片(slice)和map的使用技巧和注意事项,需要的朋友参考一下 我比较喜欢先给出代码,然后得出结论 数组 结果 切片 结果 map 运行结果 由此,我们看到数组本身传过去的是值,传到函数之后,被开辟了另外一个空间。 因为数组就是他本身。这一句好像不太好理解。 这是切片

  • 问题内容: 我最近学习了Go语言,现在对以下代码感到困惑: 结果: 问题答案: c是从数组中获取的一个切片b。这不是副本,而只是的两个前两个元素的窗口b。 由于b容量为5,c可以扩展到其他3个位置(实际上,它会创建一个新的切片,但位于内存中的同一位置)。 切片的最大容量是底层数组的容量减去切片在数组中起始位置的大小: func main() { b := make([]int, 0, 5) c :

  • 问题内容: 我进行了以下测试,即打印原始输入切片(过滤后),而没有删除元素,但是最后有一个额外的元素,使输入切片具有相同的长度,即使过滤后应该较短。 我已经看过这篇文档https://github.com/golang/go/wiki/SliceTricks#delete 但是我认为我缺少有关Go的一些技巧,因为似乎我使用的切片方法错误。 如何避免出现“输出片段”?(以正确的方式打印,包含正确的元

  • 问题内容: 我有这个简单的代码: 我期望它可以打印,但是可以打印。这里发生了什么? 问题答案: 这是因为在循环中,您使用 副本 而不是slice / array元素本身进行操作。 将使得它遍历元素的副本,并追加此一时,循环变量的地址- 这是在所有的迭代相同。因此,您将相同的指针添加3次。而且此临时变量将在最后一次迭代(数组的最后一个元素)中设置为,因此这就是为什么您看到该变量打印了3次的原因。 修