Unerwartetes Überschreibproblem mit der „Append“-Funktion von Go
In Go wird die Append-Funktion häufig verwendet, um Slices mit zusätzlichen Elementen zu erweitern. Allerdings kann es gelegentlich zu unerwartetem Verhalten kommen, wenn Zeiger an Strukturen angehängt werden.
Bedenken Sie den folgenden Codeausschnitt:
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) } }
Interessanterweise wird statt {0} {1} {2} { 3}, der Code gibt {0} {3} {3} {3} aus. Dieses unerwartete Verhalten ist auf einen grundlegenden Aspekt des Verhaltens von Go zurückzuführen:
Kopiert in for-Range-Schleifen
Go iteriert über Slices und Arrays mithilfe von for-Range-Schleifen, die eine Kopie erstellen jedes Elements während der Iteration. In unserem Code stellt die for-Range-Schleifenvariable e eine temporäre Kopie des Array-Elements b[i] dar. Leider hängen wir dann die Adresse dieser temporären Variablen an den Slice a an.
Der Fix
Um dieses Problem zu beheben, müssen wir die Adresse des anhängen ursprüngliches Array-Element anstelle der temporären Kopie. Indem wir die for-Schleife so ändern, dass sie den Index i verwendet, stellen wir sicher, dass die richtige Adresse an das Slice angehängt wird:
for i := range b { a = append(a, &b[i]) }
Diese Änderung ergibt die erwartete Ausgabe von {0} {1} {2} {3 }.
Grund für das Verhalten
Gos Mangel an wahren Referenzen trägt zu diesem Verhalten bei. In C oder Java, wo Referenzen verwendet werden, würde die Schleifenvariable direkt auf das Array-Element verweisen und so Mutationen über die Schleifenvariable ermöglichen. In Go ist die Schleifenvariable jedoch eine eindeutige Variable, die eine Kopie des Elements und keine Referenz enthält. Folglich werden an der Schleifenvariablen vorgenommene Änderungen nicht in den ursprünglichen Array-Elementen widergespiegelt.
Das obige ist der detaillierte Inhalt vonWarum führt das Anhängen von Zeigern in der Append-Funktion von Go zu unerwartetem Überschreiben?. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!