簡體   English   中英

0個長度在golang中的切片和數組

[英]0 length slices and arrays in golang

試圖找出0長度的數組和切片在Golang中的行為。 提出了兩個代碼段(我在某處找到了代碼,並對其進行了一些修改以使其適用於此)

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

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

我從網站上得知,nil數組([] int(nil))的指針值為nil,因此我決定對其進行測試。 果然如此。 我只是對make和切片數組感到困惑。 對我來說,它有意外的行為。

我對這兩者的行為感到非常困惑。 第一個在我的計算機和操場上運行良好。 我注意到第一個數組和最后一個數組的地址總是完全相同? 為什么?

為什么是這樣?

第二個是怪異的。 該代碼與上一個代碼完全相同,除了len / cap之間存在其他代碼片段。 它無法在運動場上運行,切片切片的最后一個錯誤,由於某種原因,切片的長度為3(在我的計算機上,切片的長度為0,所有切片的上限其中是272851504)。 它確實可以在我的計算機上運行。 我注意到用make創建的第一個數組的地址總是小於最后一個數組的地址。 它總是不同,並且較小(第一個),為什么? 數組地址的代碼沒有變化

另外,為什么make()甚至創建一個數組? 長度為0的數組在內存中怎么看?

我注意到第一個數組和最后一個數組的地址總是完全相同? 為什么?

為什么是這樣?

您將函數中的地址基於函數參數中的slice頭。 碰巧該函數每次都在相同的內存地址運行。 另外,作為實現細節,當您將原始文件切成零長度和零容量時,它不會使Data指針歸零。 在這兩個函數中,都將復制切片標頭,因此您甚至不必檢查原始的標頭切片。

第二個示例,您沒有正確讀取切片頭。 如果您想玩轉,無需嘗試進行指針算術,則可以直接獲取切片的地址

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

但是,如果您真的想通過指針算法檢查切片標頭,也許可以更好地闡明您需要執行的操作: 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)

}

另外,為什么make()甚至創建一個數組?

Make不會創建數組,而您標記為array的只是切片文字。

長度為0的數組在內存中怎么看?

看起來什么都沒有。 它消耗0個字節。

制作零長度切片時看到的內容很可能是指向全局零值數組的指針。 制作一堆不同類型的零長度切片,數據指針將全部相同。 正如所有空struct{}和空nil interface{}都被賦予與優化相同的值。 這完全是一個實現細節,因為不希望您訪問該Data值。 將切片切成零長度和容量時,運行時也不會將數據指針歸零。 由於這兩種行為,任何切片中的數據指針很少為零。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM