Heim >Backend-Entwicklung >Golang >Warum zeigt die „for range'-Schleife von Go ein unterschiedliches Verhalten bei Funktionsliteralen?

Warum zeigt die „for range'-Schleife von Go ein unterschiedliches Verhalten bei Funktionsliteralen?

Susan Sarandon
Susan SarandonOriginal
2024-12-10 20:52:11421Durchsuche

Why Does Go's `for range` Loop Exhibit Different Behavior with Function Literals?

Unterschiedliches Schleifenverhalten in Go verstehen

Beim Erstellen von Schleifen in Go ist es wichtig, das Verhalten der for-Range-Schleife zu verstehen. Betrachten Sie die folgenden zwei Schleifenvarianten, die ein unterschiedliches Verhalten aufweisen:

Schleifenvariante 1:

func loop1() {

    actions := make(map[string]func())

    for _, cmd := range cmds {
        actions[cmd] = func() {
            fmt.Println(cmd)
        }
    }
    for _, action := range actions {
        action()
    }
}

Schleifenvariante 2:

func loop2() {

    actions := make(map[string]func())

    for i, cmd := range cmds {
        command := cmds[i]
        actions[cmd] = func() {
            fmt.Println(command)
        }
    }
    for _, action := range actions {
        action()
    }
}

Ausgabe Beobachtungen:

  • Loop1 erzeugt die Ausgabe: „update“ (dreimal wiederholt)
  • Loop2 erzeugt die Ausgabe: „delete“, „update“, „create“

Grundlegendes Problem in der Schleifenvariation 1:

Das Problem liegt in der Schleife func loop1(). Jede Schleifeniteration weist der Aktionszuordnung ein Funktionsliteral zu. Dieses Funktionsliteral referenziert die Schleifenvariable cmd. Es gibt jedoch nur eine Instanz von cmd, und wenn die Schleife beendet ist, enthält sie den letzten Wert im Befehlsabschnitt, nämlich „update“. Dies bedeutet, dass alle eingeschlossenen Funktionen auf dieselbe Schleifenvariable (cmd) verweisen, was dazu führt, dass alle Funktionen beim Aufruf „Update“ ausgeben.

Lösung:

Um dies zu beheben , erstellen Sie innerhalb jeder Schleifeniteration eine Kopie der Schleifenvariablen, sodass jedes Funktionsliteral sein eigenes unabhängiges hat kopieren:

func loop1() {
    actions := make(map[string]func())

    for _, cmd := range cmds {
        cmd2 := cmd
        actions[cmd] = func() {
            fmt.Println(cmd2) // Refer to the detached, copy variable!
        }
    }
    for _, action := range actions {
        action()
    }
}

Schlussfolgerung:

Zusammenfassend lässt sich sagen, dass es bei der Verwendung der for-Range-Schleife wichtig ist, den Umfang und die Referenzen von Schleifenvariablen zu berücksichtigen. Durch die Sicherstellung, dass bei Bedarf Kopien von Schleifenvariablen erstellt werden, wird ein korrektes Verhalten sichergestellt, insbesondere beim Umgang mit Funktionsliteralen, die auf diese Variablen verweisen.

Das obige ist der detaillierte Inhalt vonWarum zeigt die „for range'-Schleife von Go ein unterschiedliches Verhalten bei Funktionsliteralen?. 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