简体   繁体   English

0个长度在golang中的切片和数组

[英]0 length slices and arrays in golang

Was trying to figure out how 0 length arrays and slices behaved in Golang. 试图找出0长度的数组和切片在Golang中的行为。 Came up with two snippets of code (I found the code somewhere and modified it a bit to work with this) 提出了两个代码段(我在某处找到了代码,并对其进行了一些修改以使其适用于此)

https://play.golang.org/p/ew2YYgvpGC https://play.golang.org/p/ew2YYgvpGC

https://play.golang.org/p/jm2p6L6WCG https://play.golang.org/p/jm2p6L6WCG

I learnt from the website that nil arrays ([]int(nil)) have a pointer value of nil, so I decided to test it. 我从网站上得知,nil数组([] int(nil))的指针值为nil,因此我决定对其进行测试。 Sure enough, that is the case. 果然如此。 I'm just confused on make and slicing an array. 我只是对make和切片数组感到困惑。 It has unexpected behaviour for me. 对我来说,它有意外的行为。

I am really confused by the behaviour of these two. 我对这两者的行为感到非常困惑。 The first one runs fine on my computer and on the playground. 第一个在我的计算机和操场上运行良好。 I've noticed that the address of the first and last array is always the exact same? 我注意到第一个数组和最后一个数组的地址总是完全相同? Why? 为什么?

Why is this? 为什么是这样?

The second one is weirder. 第二个是怪异的。 This is the exact same code as the previous one, except there are snippets of other code for the len/cap in between. 该代码与上一个代码完全相同,除了len / cap之间存在其他代码片段。 It does not run on the go playground, there is an error at the last one with the sliced array, for some reason, the slice gets a length of 3 (on my computer it is 0 for the last one, and the cap for all of them is 272851504). 它无法在运动场上运行,切片切片的最后一个错误,由于某种原因,切片的长度为3(在我的计算机上,切片的长度为0,所有切片的上限其中是272851504)。 It does run on my computer however. 它确实可以在我的计算机上运行。 I noticed that the address of the first array created with make is always smaller than the last one. 我注意到用make创建的第一个数组的地址总是小于最后一个数组的地址。 Its always different, and a bit smaller (the first one), why? 它总是不同,并且较小(第一个),为什么? There is no change in the code for the address of the array 数组地址的代码没有变化

Also, why does make() even create an array? 另外,为什么make()甚至创建一个数组? How does an array of length 0 even look in memory? 长度为0的数组在内存中怎么看?

I've noticed that the address of the first and last array is always the exact same? 我注意到第一个数组和最后一个数组的地址总是完全相同? Why? 为什么?

Why is this? 为什么是这样?

You are basing the addresses in your function on the slice header in the function arguments. 您将函数中的地址基于函数参数中的slice头。 And by chance that function happens to run at the same memory address each time. 碰巧该函数每次都在相同的内存地址运行。 Also, as an implementation detail, when you slice the original down to zero length and capacity, it doesn't zero out the Data pointer. 另外,作为实现细节,当您将原始文件切成零长度和零容量时,它不会使Data指针归零。 In both your functions, the slice header is copied, so you're not even examining the original header slice to begin with. 在这两个函数中,都将复制切片标头,因此您甚至不必检查原始的标头切片。

The second example, you're not correctly reading out the slice header. 第二个示例,您没有正确读取切片头。 If you want to play around, you don't need to try and do pointer arithmetic, and you you can take the address of the slice directly 如果您想玩转,无需尝试进行指针算术,则可以直接获取切片的地址

hdr := (*reflect.SliceHeader)(unsafe.Pointer(&slice))

Though, if you really want to inspect a slice header via pointer arithmetic, maybe this can better clarify what you need to do: https://play.golang.org/p/GL6NtyPNs8 但是,如果您真的想通过指针算法检查切片标头,也许可以更好地阐明您需要执行的操作: https : //play.golang.org/p/GL6NtyPNs8

func InspectSlice(slice *[]int) {
    // Get the header directly by converting it to a reflect.SliceHeader
    hdr := (*reflect.SliceHeader)(unsafe.Pointer(slice))

    // Create a header for comparison via pointer manipulation
    address := (uintptr)(unsafe.Pointer(slice))
    lenAddr := address + unsafe.Sizeof(address)
    capAddr := lenAddr + unsafe.Sizeof(int(0))

    unsafeHdr := reflect.SliceHeader{
        Data: *(*uintptr)(unsafe.Pointer(address)),
        Len:  *(*int)(unsafe.Pointer(lenAddr)),
        Cap:  *(*int)(unsafe.Pointer(capAddr)),
    }

    fmt.Printf("Real Header:  %#v\n", *hdr)
    fmt.Printf("UnsafeHeader: %#v\n", unsafeHdr)

}

Also, why does make() even create an array? 另外,为什么make()甚至创建一个数组?

Make doesn't create an array, and what you have labeled as array is just a slice literal. Make不会创建数组,而您标记为array的只是切片文字。

How does an array of length 0 even look in memory? 长度为0的数组在内存中怎么看?

It doesn't look like anything. 看起来什么都没有。 It consumes 0 bytes. 它消耗0个字节。

What you are seeing when making a zero-length slice is most likely a pointer to a global zero value array. 制作零长度切片时看到的内容很可能是指向全局零值数组的指针。 Make a bunch zero length slices of different types, and the Data pointers will all be the same. 制作一堆不同类型的零长度切片,数据指针将全部相同。 Just as all empty struct{} and empty nil interface{} are given the same value as an optimization. 正如所有空struct{}和空nil interface{}都被赋予与优化相同的值。 This is entirely an implementation detail, as you are not expected to access that Data value. 这完全是一个实现细节,因为不希望您访问该Data值。 When slicing a slice back to zero length and capacity, the runtime also doesn't zero out the Data pointer. 将切片切成零长度和容量时,运行时也不会将数据指针归零。 Because of these two behaviors, the Data pointer in any slice is rarely going to be nil. 由于这两种行为,任何切片中的数据指针很少为零。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM