Heim > Backend-Entwicklung > Golang > Warum erzeugt die Append-Funktion von Go beim Anhängen von Zeigern aus einer Bereichsschleife unerwartete Ergebnisse?

Warum erzeugt die Append-Funktion von Go beim Anhängen von Zeigern aus einer Bereichsschleife unerwartete Ergebnisse?

Patricia Arquette
Freigeben: 2024-12-08 03:08:11
Original
146 Leute haben es durchsucht

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

Unbeabsichtigtes Überschreiben in der „Anhänge“-Funktion von Go

In Go kann das Erkunden der Nuancen des Anhängens an Slices manchmal zu unerwarteten Ergebnissen führen. Sehen wir uns ein Beispiel an, das dieses Verhalten veranschaulicht.

Betrachten Sie den folgenden Code:

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)
    }
}
Nach dem Login kopieren

Interessanterweise wird statt {0} {1} {2} {3} die Ausgabe ausgegeben liest sich als {0} {3} {3} {3}. Um dieses Rätsel zu lösen, analysieren wir die Funktion „append“.

In Go erwartet „append“ einen Zeiger auf den Slice, zu dem wir Elemente hinzufügen. In unserem Beispiel speichern wir Zeiger auf „Foo“-Instanzen korrekt im Slice „a“.

Beim Durchlaufen der Elemente des Arrays „b“ stoßen wir jedoch auf ein subtiles Problem. Die „Range“-Syntax iteriert über eine Kopie jedes Elements und nicht über das eigentliche Element selbst. Daher fügen wir fortlaufend Zeiger auf Kopien der „Foo“-Instanz „e“ hinzu, die in der letzten Iteration auf „Foo{3}“ verweist.

Um dieses Verhalten zu korrigieren, müssen wir referenzieren die tatsächlichen Elemente von „b“ in unserer „Anhänge“-Operation:

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

Diese Änderung stellt sicher, dass wir Zeiger direkt auf die Elemente in „b“ hinzufügen, was zur gewünschten Ausgabe führt: {0} {1} {2} {3}.

Es ist entscheidend, den zugrunde liegenden Grund für dieses Verhalten zu verstehen. In Go sind Zeiger Werte, die beim Bearbeiten von Daten als Speicheradressen interpretiert werden. Daher iterieren „Bereichs“-Schleifen über Kopien von Werten und nicht über die Originalobjekte. Dieses Wissen hilft zu verstehen, warum in unserem ursprünglichen Code drei Elemente auf dieselbe „Foo{3}“-Instanz verwiesen.

Das obige ist der detaillierte Inhalt vonWarum erzeugt die Append-Funktion von Go beim Anhängen von Zeigern aus einer Bereichsschleife unerwartete Ergebnisse?. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Quelle:php.cn
Erklärung dieser Website
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn
Neueste Artikel des Autors
Beliebte Tutorials
Mehr>
Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage