首頁 > 後端開發 > Golang > 為什麼在 Go `for...range` 循環中加入指標會產生意外結果?

為什麼在 Go `for...range` 循環中加入指標會產生意外結果?

Barbara Streisand
發布: 2024-12-30 17:03:12
原創
772 人瀏覽過

Why Does Appending Pointers in a Go `for...range` Loop Produce Unexpected Results?

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

來源:php.cn
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
作者最新文章
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板