首頁 > 後端開發 > Golang > 為什麼 Go 的 `append` 函數在從範圍循環追加指標時會產生意外的結果?

為什麼 Go 的 `append` 函數在從範圍循環追加指標時會產生意外的結果?

Patricia Arquette
發布: 2024-12-08 03:08:11
原創
171 人瀏覽過

Why Does Go's `append` Function Produce Unexpected Results When Appending Pointers from a Range Loop?

Go 的「append」函數中的意外覆蓋

在Go 中,探索附加到切片的細微差別有時會導致意想不到的結果。讓我們深入研究一個展示此行為的範例。

考慮以下程式碼:

import "fmt"

type Foo struct {
    val int
}

func main() {
    a := make([]*Foo, 1)
    a[0] = &Foo{0}

    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}。為了解開這個謎題,讓我們來剖析「append」函數。

在 Go 中,「append」需要一個指向我們要加入元素的切片的指標。在我們的範例中,我們正確地將指向「Foo」實例的指標儲存在切片「a」中。

但是,當迴圈遍歷數組「b」的元素時,我們遇到了一個微妙的問題。 「範圍」語法迭代每個元素的副本而不是實際元素本身。因此,我們不斷添加指向“Foo”實例“e”副本的指針,該實例在最終迭代中指向“Foo{3}”。

要修正此行為,我們需要引用「append」操作中「b」的實際元素:

for i := range b {
    a = append(a, &b[i])
}
登入後複製

此修改可確保我們直接將指標新增至「b」的元素,從而產生所需的輸出:{0} {1} {2} {3}。

了解此行為的根本原因至關重要。在 Go 中,指標是值,在操作資料時解釋為記憶體位址。因此,“範圍”循環迭代值的副本而不是原始物件。這些知識有助於理解為什麼在我們的初始程式碼中,三個元素指向同一個「Foo{3}」實例。

以上是為什麼 Go 的 `append` 函數在從範圍循環追加指標時會產生意外的結果?的詳細內容。更多資訊請關注PHP中文網其他相關文章!

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