Heim > Backend-Entwicklung > Golang > Warum führt die Append-Funktion von Go zu unerwarteten Ergebnissen, wenn Zeiger aus einer for-range-Schleife angehängt werden?

Warum führt die Append-Funktion von Go zu unerwarteten Ergebnissen, wenn Zeiger aus einer for-range-Schleife angehängt werden?

Linda Hamilton
Freigeben: 2024-12-22 22:35:15
Original
756 Leute haben es durchsucht

Why does Go's `append` function produce unexpected results when appending pointers from a for-range loop?

Unerwartetes Anhängeverhalten bei Go-Slices: Eine Erklärung

In Go verhält sich die Append-Funktion beim Anhängen an ein Zeigersegment interessant. Um dies zu veranschaulichen, betrachten Sie den folgenden Code:

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

Entgegen der Erwartung, dass der Code {0} {1} {2} {3} ausgeben würde, gibt er stattdessen {0} {3} { aus. 3} {3}. Der Grund für diese Diskrepanz liegt in der Natur der Bereichsvariablen der for-Schleife.

Die Bereichsvariable verstehen

Die for-range-Schleife in Go erstellt eine Kopie jedes Elements im Array oder Slice, über das iteriert wird. In diesem Fall ist e eine Kopie des Elements im Array b. Daher ist e selbst nicht das Element in b; Vielmehr handelt es sich um eine temporäre Variable, die den Wert des Elements enthält.

Beim Anhängen an das Segment a hängt der Code die Adresse von e an, nicht die Adresse des tatsächlichen Elements in b. Da e für alle Iterationen dieselbe Kopie ist, wird derselbe Zeiger dreimal an a angehängt. Somit ist der letzte Wert, der e zugewiesen ist (das ist Foo{3}), derjenige, der wiederholt gedruckt wird.

Beheben des Verhaltens

Um dieses Verhalten zu beheben, verwenden Sie den Code sollte die Adresse des tatsächlichen Elements in b anhängen, nicht die Adresse von e. Die korrigierte Schleife würde so aussehen:

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

Durch das Anhängen von &b[i] anstelle von &e stellt der Code sicher, dass jedes Element in b zu a hinzugefügt wird. Folglich wird die korrekte Ausgabe {0} {1} {2} {3} gedruckt.

Grund für das anfängliche Verhalten

Dieses unerwartete Verhalten ist auf die Abwesenheit zurückzuführen der wahren Referenzen in Go. Go verfügt über Zeigertypen und Nicht-Zeigertypen, aber keine Referenzen. Die Bereichsvariable ist einfach eine lokale Variable, die einen Wert enthält, der ein Zeiger oder ein Nicht-Zeiger sein kann. Es kann keine Referenz enthalten.

Daher manipuliert man bei der Bearbeitung der Bereichsvariablen nur den Wert, nicht das Element selbst. Um das tatsächliche Element zu ändern, muss man den Wert der Bereichsvariablen zuweisen und so den Wert effektiv kopieren. Dieser Wert wird dann in der nächsten Iteration überschrieben.

Das obige ist der detaillierte Inhalt vonWarum führt die Append-Funktion von Go zu unerwarteten Ergebnissen, wenn Zeiger aus einer for-range-Schleife angehängt werden?. 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