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中文網其他相關文章!