理解Go中append的奇怪行為
在Go中,append函數對切片進行操作以添加新元素。但是,在 for range 迴圈中將指標附加到陣列中的元素時,使用者可能會遇到意外行為。
請考慮以下範例:
import "fmt" type Foo struct { val int } func main() { var a = make([]*Foo, 1) a[0] = &Foo{0} var b = [3]Foo{Foo{1}, Foo{2}, Foo{3}} for _, e := range b { a = append(a, &e) } for _, e := range a { fmt.Printf("%v ", *e) } }
預期輸出:{0} {1} {2} {3}
實際輸出:{0} {3} {3} {3}
該行為的原因
出現此意外行為是因為 for range 循環迭代元素的副本,而不是原始元素本身。在這種情況下,循環變數 e 會保存數組目前元素的副本。附加切片時,會新增循環變數的位址,該位址為所有迭代引用相同的記憶體位置。因此,當遇到陣列的最後一個元素時,所有附加位址都指向同一個元素。
修正
要解決此問題,append 函數應該是與原始數組元素的位址一起使用,而不是與循環變數一起使用。以下是修正後的程式碼:
for i := range b { a = append(a, &b[i]) }
經過此修改,輸出將如預期:{0} {1} {2} {3}。
結論
理解 Go 中指標和非指標類型之間的區別對於正確處理記憶體引用至關重要。使用 for range 迴圈時,必須考慮是否需要存取原始元素還是副本,並相應地使用適當的語法。
以上是為什麼在 Go `for...range` 循環中加入指標會產生意外結果?的詳細內容。更多資訊請關注PHP中文網其他相關文章!