doudizhi947129 2015-03-23 17:13
浏览 360

0个长度在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?

  • 写回答

1条回答 默认 最新

  • duanfu2562 2015-03-23 18:00
    关注

    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
    ", *hdr)
        fmt.Printf("UnsafeHeader: %#v
    ", 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.

    评论

报告相同问题?

悬赏问题

  • ¥15 python变量和列表之间的相互影响
  • ¥15 写一个方法checkPerson,入参实体类Person,出参布尔值
  • ¥15 我想咨询一下路面纹理三维点云数据处理的一些问题,上传的坐标文件里是怎么对无序点进行编号的,以及xy坐标在处理的时候是进行整体模型分片处理的吗
  • ¥15 CSAPPattacklab
  • ¥15 一直显示正在等待HID—ISP
  • ¥15 Python turtle 画图
  • ¥15 关于大棚监测的pcb板设计
  • ¥15 stm32开发clion时遇到的编译问题
  • ¥15 lna设计 源简并电感型共源放大器
  • ¥15 如何用Labview在myRIO上做LCD显示?(语言-开发语言)