在Go 中,將元素追加到循環內的切片可能會意外更改從同一底層數組創建的現有切片的值。
問題源自於切片引用底層陣列值的方式。當您追加到切片時,它可能會修改現有陣列或建立一個新陣列。但是,如果切片是使用 make 函數建立的,則它始終引用相同的底層數組。
考慮以下程式碼:
<code class="go">func create(iterations int) []int { a := make([]int, 0) for i := 0; i < iterations; i++ { a = append(a, i) } return a } func main() { sliceFromLoop() sliceFromLiteral() } func sliceFromLoop() { i := create(11) j := append(i, 100) g := append(i, 101) h := append(i, 102) fmt.Printf("i: %v\nj: %v\ng: %v\nh:%v\n", i, j, g, h) } func sliceFromLiteral() { i := []int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10} j := append(i, 100) g := append(i, 101) h := append(i, 102) fmt.Printf("i: %v\nj: %v\ng: %v\nh:%v\n", i, j, g, h) }</code>
在sliceFromLoop 中函數中,所有新切片(j, g, h) 與初始切片i 共用相同的底層數組。這意味著當我們追加到 i 時,它會修改所有其他切片的最後一個元素。
為了避免這種行為,建議在追加之前複製切片到它。 copy 函數指派一個與原始切片具有相同元素的新切片。
<code class="go">func sliceFromLoopFixed() { i := create(11) j := append([]int{}, i..., 100) g := append([]int{}, i..., 101) h := append([]int{}, i..., 102) fmt.Printf("i: %v\nj: %v\ng: %v\nh:%v\n", i, j, g, h) }</code>
在這種情況下,新切片 j、g 和 h 都有自己的底層數組,因此 i 的值不受影響通過附錄。
以上是為什麼從同一底層陣列建立的切片在 Go 中追加時會表現出意外的行為?的詳細內容。更多資訊請關注PHP中文網其他相關文章!