首頁 >後端開發 >Golang >為什麼重新切片 Go 切片會導致意外的容量值?

為什麼重新切片 Go 切片會導致意外的容量值?

Barbara Streisand
Barbara Streisand原創
2024-12-24 10:44:13623瀏覽

Why Does Re-Slicing a Go Slice Result in Unexpected Capacity Values?

Golang 中的重新切片

理解切片的行為可能會令人困惑,尤其是在涉及重新切片時。在此程式碼段中:

package main

import "fmt"

func main() {
    a := make([]int, 5)
    printSlice("a", a)
    b := make([]int, 0, 5)
    printSlice("b", b)
    c := b[:2]
    printSlice("c", c)
    d := c[2:5]
    printSlice("d", d)
}

func printSlice(s string, x []int) {
    fmt.Printf("%s len=%d cap=%d %v\n",
        s, len(x), cap(x), x)
}

輸出顯示出意外的結果:

a len=5 cap=5 [0 0 0 0 0]
b len=0 cap=5 []
c len=2 cap=5 [0 0] 
d len=3 cap=3 [0 0 0]

為什麼 c 的容量為 5 而不是 2?要回答這個問題,我們需要了解 Golang 中切片的概念。

切片是對陣列的輕量級引用。當我們建立切片時,我們提供範圍操作(例如,[:2])來指定引用數組的開始和結束索引。但是,此範圍操作不會建立基礎數組的副本。相反,它會建立一個共享相同基礎資料的新切片。

在給定的範例中,b 是容量為 5 的空切片。當我們將 c 建立為 b 的切片,範圍為 [ :2],我們本質上是建立對 b 的前兩個元素的參考。由於 b 的容量為 5,因此 c 可以擴充為最多包含 5 個元素,即使目前僅引用 2 個元素。這就是為什麼 c 的容量為 5,儘管它的長度為 2。

此外,當我們將d 創建為範圍為[2:5] 的c 的切片時,我們實際上是在創建一個共享的切片與b 相同的基礎數據,但從索引2 開始一直延伸到索引5。由於b 的容量為5,因此d 的容量為3 (5-2).

下面的程序更清楚地說明了這種行為:

func main() {
    b := make([]int, 0, 5)
    c := b[:2]
    d := c[1:5] // equivalent to d := b[1:5]
    d[0] = 1
    printSlice("c", c)
    printSlice("d", d)
}

輸出:

c len=2 cap=5 [0 1] // modifying d has modified c
d len=4 cap=4 [1 0 0 0] 

如您所見,修改d 也可以修改了c,證明c 和d 都是同一底層陣列b 上的視窗。

以上是為什麼重新切片 Go 切片會導致意外的容量值?的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn