首頁 >後端開發 >Golang >為什麼在 Go 的 `append` 函數中追加指標會導致意外覆蓋?

為什麼在 Go 的 `append` 函數中追加指標會導致意外覆蓋?

Barbara Streisand
Barbara Streisand原創
2024-12-25 03:36:17742瀏覽

Why Does Appending Pointers in Go's `append` Function Lead to Unexpected Overwriting?

Go 的「append」函數會出現意外覆蓋問題

在 Go 中,append 函數常用於以附加元素擴展切片。但是,有時,將指標附加到結構時可能會出現意外行為。

考慮以下程式碼片段:

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}。這種意外的行為源自於Go 行為的一個基本面向:

在for Range 循環中複製

Go 使用for range 循環迭代切片和數組,這會建立一個副本迭代過程中每個元素的值。在我們的程式碼中,for range 迴圈變數 e 表示陣列元素 b[i] 的暫存副本。不幸的是,我們隨後將此臨時變數的位址附加到切片 a。

修正

要解決此問題,我們需要附加原始數組元素而不是臨時副本。透過修改for 循環以使用索引i,我們確保將正確的位址附加到切片:

for i := range b {
    a = append(a, &b[i])
}

此變更會產生{0} {1} {2} {3 的預期輸出}.

行為的原因

Go 缺乏真正的引用導致了這種情況行為。在使用引用的 C 或 Java 中,循環變數將直接引用數組元素,從而允許透過循環變數進行更改。然而,在 Go 中,循環變數是一個不同的變量,它保存元素的副本,而不是引用。因此,對循環變數所做的更改不會反映在原始數組元素中。

以上是為什麼在 Go 的 `append` 函數中追加指標會導致意外覆蓋?的詳細內容。更多資訊請關注PHP中文網其他相關文章!

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