Heim >Backend-Entwicklung >Golang >Warum erfordert Go das explizite Kopieren von Schleifenvariablen in Abschlüssen?

Warum erfordert Go das explizite Kopieren von Schleifenvariablen in Abschlüssen?

Barbara Streisand
Barbara StreisandOriginal
2024-12-24 01:44:11382Durchsuche

Why Does Go Require Explicit Copying of Loop Variables in Closures?

Erfasster Abschluss in Go (für Schleifenvariablen)

Der Go-Compiler erfasst for...range-Schleifenvariablen nicht automatisch als lokal zugewiesen Abschlussvariablen. Stattdessen behandelt Go alle for-Schleifen (einschließlich for...range-Schleifen) ähnlich und erfordert das explizite Kopieren von Schleifenvariablen in lokale Abschlüsse, um das erwartete Verhalten sicherzustellen.

Gründe für das Kopieren von Schleifenvariablen

Dieses Verhalten ist auf die konsequente Handhabung von for-Schleifen durch Go zurückzuführen. In allen Arten von for-Schleifen, einschließlich for...range-Schleifen, sind Schleifenvariablen auf den Block der Schleife beschränkt. Nachdem der Block der Schleife endet, ist die Schleifenvariable nicht mehr zugänglich.

In for...range-Schleifen wird die Schleifenvariable bei jeder Iteration der Schleife auf einen neuen Wert initialisiert. Der innerhalb der Schleife erstellte Abschluss verweist jedoch weiterhin auf die ursprüngliche Schleifenvariable. Um sicherzustellen, dass der Abschluss über eine unabhängige Kopie der Schleifenvariablen verfügt, muss diese einer lokalen Variablen innerhalb des Abschlusses zugewiesen werden.

Codebeispiel

Unten finden Sie ein Beispiel Dies verdeutlicht die Notwendigkeit des Kopierens von Schleifenvariablen:

func main() {
    m := make(map[int32]int32)
    for i := int32(1); i <= 10; i++ {
        m[i] = i
    }

    l := make([]func() (int32, int32), 0)
    for k, v := range m {
        l = append(l, func() (int32, int32) {
            return k, v
        })
    }

    for _, f := range l {
        k, v := f()
        fmt.Println(k, v)
    }
}

In diesem Beispiel wird erwartet, dass sich die Schleifenvariable k während jeder Iteration der for...range-Schleife ändert. Der Abschluss erfasst jedoch die ursprüngliche Schleifenvariable k, die während der gesamten Schleife gleich bleibt. Infolgedessen gibt der Code zehnmal dasselbe Wertepaar (10, 10) aus.

Lösung: Schleifenvariablen kopieren

Um das Problem zu beheben, wird die Schleife Variablen müssen innerhalb des Abschlusses in lokale Variablen kopiert werden:

func main() {
    m := make(map[int32]int32)
    for i := int32(1); i <= 10; i++ {
        m[i] = i
    }

    l := make([]func() (int32, int32), 0)
    for k, v := range m {
        kLocal, vLocal := k, v
        l = append(l, func() (int32, int32) {
            return kLocal, vLocal
        })
    }

    for _, f := range l {
        k, v := f()
        fmt.Println(k, v)
    }
}

Der Abschluss erfasst nun die lokalen Variablen kLocal und vLocal, die Halten Sie die während jeder Iteration der for...range-Schleife zugewiesenen Werte unabhängig voneinander. Der Code gibt die erwarteten Wertepaare (1, 1), (2, 2), ..., (10, 10) korrekt aus.

Das obige ist der detaillierte Inhalt vonWarum erfordert Go das explizite Kopieren von Schleifenvariablen in Abschlüssen?. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
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