Heim > Backend-Entwicklung > Golang > Warum gibt „defer func() { fmt.Println(i) }()' „44444' in Go aus, während „defer func(n int) { fmt.Println(n) }(i)' korrekt „43210' ausgibt? ?

Warum gibt „defer func() { fmt.Println(i) }()' „44444' in Go aus, während „defer func(n int) { fmt.Println(n) }(i)' korrekt „43210' ausgibt? ?

DDD
Freigeben: 2024-11-10 18:54:02
Original
490 Leute haben es durchsucht

Why does `defer func() { fmt.Println(i) }()` print

Verzögerte Funktionsaufrufe und Abschlusserfassung

In Go ermöglicht uns die Defer-Anweisung, eine Funktion auszuführen, kurz bevor die umgebende Funktion zurückkehrt. Ein wichtiger Aspekt von defer ist die Art und Weise, wie Schließungen behandelt werden.

In diesem Codeausschnitt:

package main

import "fmt"

func main() {
    var whatever [5]struct{}

    for i := range whatever {
        fmt.Println(i)
    } // part 1

    for i := range whatever {
        defer func() { fmt.Println(i) }()  // part 2
    }

    for i := range whatever {
        defer func(n int) { fmt.Println(n) }(i)  // part 3
    }
}
Nach dem Login kopieren

Teil 1 gibt einfach die Werte von i von 0 bis 4 aus. Teil 2 demonstriert dies jedoch ein interessantes Verhalten. Anstatt die erwarteten Werte von 0 bis 4 auszugeben, wird „44444“ ausgegeben.

Das liegt daran, dass der Abschluss in Teil 2 die i-Variable erfasst. Wenn der Abschluss später ausgeführt wird, hat die i-Variable den Wert, den sie in der letzten Iteration der Range-Anweisung hatte, nämlich 4. Als Ergebnis geben alle verzögerten Funktionsaufrufe 4 aus.

Im Gegensatz dazu part 3 erfasst keine äußeren Variablen. Gemäß den Go-Spezifikationen „werden bei jeder Ausführung der ‚defer‘-Anweisung der Funktionswert und die Parameter des Aufrufs wie gewohnt ausgewertet und erneut gespeichert, aber die eigentliche Funktion wird nicht aufgerufen.“ Das bedeutet, dass jeder der verzögerten Funktionsaufrufe einen anderen Wert des Parameters „n“ hat, der dem Wert von „i“ zum Zeitpunkt der Ausführung der „defer“-Anweisung entspricht.

Daher ist Teil 3 korrekt gibt „43210“ aus, da die verzögerten Funktionsaufrufe in LIFO-Reihenfolge (last-in, first-out) ausgeführt werden, bevor die umgebende Funktion zurückkehrt.

Es ist wichtig, sich den Funktionsausdruck zu merken in 'defer f()' wird zum Zeitpunkt der Ausführung der defer-Anweisung nicht ausgeführt, während der Ausdruck in 'defer f(e)' sofort ausgewertet wird.

Das obige ist der detaillierte Inhalt vonWarum gibt „defer func() { fmt.Println(i) }()' „44444' in Go aus, während „defer func(n int) { fmt.Println(n) }(i)' korrekt „43210' ausgibt? ?. 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
Beliebte Tutorials
Mehr>
Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage