Heim > Backend-Entwicklung > Golang > Warum zeigen in einer Schleife angehängte Slices beim Erstellen neuer Slices in Go ein unerwartetes Verhalten?

Warum zeigen in einer Schleife angehängte Slices beim Erstellen neuer Slices in Go ein unerwartetes Verhalten?

Linda Hamilton
Freigeben: 2024-11-02 19:10:03
Original
324 Leute haben es durchsucht

Why do slices appended in a loop exhibit unexpected behavior when creating new slices in Go?

Unerwartetes Slice-Anhängeverhalten in Go

Im Bereich der Go-Programmierung ist beim Anhängen von Elementen an ein darin enthaltenes Slice ein ungewöhnliches Verhalten aufgetreten eine Schleife und versucht anschließend, basierend auf dem Ergebnis der Schleife neue Slices zu erstellen. Interessanterweise überschreibt der letzte Anhängevorgang die Slices, die aus vorherigen Anhängen erstellt wurden.

Untersuchung des Problems

Bedenken Sie den folgenden Codeausschnitt:

<code class="go">func create(iterations int) []int {
    a := make([]int, 0)
    for i := 0; i < iterations; i++ {
        a = append(a, i)
    }
    return a
}</code>
Nach dem Login kopieren

Beim Aufruf von create(11) und beim Erstellen neuer Slices durch Anhängen von Elementen (d. h. j := append(i, 100), g := append(i, 101), h := append(i, 102)), eins würde erwarten, dass die letzten Elemente dieser Slices (j, g und h) 100, 101 bzw. 102 sind. Überraschenderweise sind in diesem Fall jedoch alle 102.

Dieses Verhalten steht in krassem Gegensatz zu dem, was passiert, wenn neue Slices aus einem Slice-Literal erstellt werden, wie unten gezeigt:

<code class="go">func sliceFromLiteral() {
    i := []int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
    j := append(i, 100)
    g := append(i, 101)
    h := append(i, 102)
    fmt.Printf("i: %v\nj: %v\ng: %v\nh:%v\n", i, j, g, h)
}</code>
Nach dem Login kopieren

In diesem Fall zeigen j, g und h das erwartete Verhalten, wobei die letzten Elemente 100, 101 bzw. 102 sind.

Eintauchen in die Grundursache

Um das Geheimnis hinter diesem unerwarteten Verhalten zu lüften, ist es wichtig zu verstehen, dass der Anhängevorgang nicht nur das zugrunde liegende Array ändert, sondern auch ein neues Slice zurückgibt. Dies impliziert, dass die Slices j, g und h tatsächlich auf dasselbe zugrunde liegende Array verweisen. Wenn also das letzte Anhängen (append(i, 102)) ausgeführt wird, ändert es das letzte Element des zugrunde liegenden Arrays und überschreibt effektiv die Werte in j, g und h.

The Idiomatic Lösung

Um dieses unerwartete Verhalten zu vermeiden, ist es unbedingt erforderlich, das Slice zu kopieren, bevor Sie versuchen, etwas anzuhängen. Dadurch wird ein neues zugrunde liegendes Array erstellt und sichergestellt, dass der ursprüngliche Slice unverändert bleibt. Der folgende Code veranschaulicht die idiomatische Art und Weise, mehrere neue Slices basierend auf vorhandenen zu erstellen:

<code class="go">func makeFromSlice(sl []int) []int {
    result := make([]int, len(sl))
    copy(result, sl)
    return result
}</code>
Nach dem Login kopieren

Mit diesem Ansatz kann man mühelos neue Slices erstellen und gleichzeitig die Integrität der Originaldaten bewahren.

Die Slice-Literal-Ausnahme

Das besondere Verhalten, das bei aus Schleifen erstellten Slices beobachtet wird, erstreckt sich nicht auf Slices, die aus Literalen initialisiert werden. Dies ist darauf zurückzuführen, dass Go ein neues Array zuweist, wenn eine Anhängeoperation die Kapazität des Hintergrundarrays überschreiten würde. Dieses Verhalten ist unabhängig davon, ob das Slice aus einem Literal oder einer Variablen erstellt wird, und ist lediglich eine Folge davon, wie Arrays intern in Go behandelt werden.

Das obige ist der detaillierte Inhalt vonWarum zeigen in einer Schleife angehängte Slices beim Erstellen neuer Slices in Go ein unerwartetes Verhalten?. 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