简体   繁体   中英

0 length slices and arrays in golang

Was trying to figure out how 0 length arrays and slices behaved in 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/jm2p6L6WCG

I learnt from the website that nil arrays ([]int(nil)) have a pointer value of nil, so I decided to test it. Sure enough, that is the case. I'm just confused on make and slicing an array. 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. 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). 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. 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? How does an array of length 0 even look in memory?

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. 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. 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

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 doesn't create an array, and what you have labeled as array is just a slice literal.

How does an array of length 0 even look in memory?

It doesn't look like anything. It consumes 0 bytes.

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. This is entirely an implementation detail, as you are not expected to access that Data value. 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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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