微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

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

如何解决底层数组在 Golang 的“切片”中的行为方式

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

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

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

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

这是怎么发生的?

切片中数组的地址取自此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]

解决方法

这个操作:

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

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

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。