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) } }
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]) }
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!