Heim >Backend-Entwicklung >Golang >Wie verwende ich „defer' in Go mit geänderten Variablen richtig?
In Go können wir mit der „defer“-Anweisung die Ausführung einer Funktion planen, kurz bevor die umgebende Funktion zurückkehrt. Dies kann jedoch zu Verwirrung führen, wenn es um Variablen geht, die innerhalb der einschließenden Funktion geändert werden.
Betrachten Sie die folgende Funktion:
func printNumbers() { var x int defer fmt.Println(x) for i := 0; i < 5; i++ { x++ } }
Gemäß der Go-Spezifikation: Wenn eine „Defer“-Anweisung ausgeführt wird, werden der Funktionswert und die Parameter ausgewertet und für die spätere Ausführung gespeichert. Das bedeutet, dass, wenn die Funktion schließlich aufgerufen wird, der Wert von x immer noch 0 sein wird, da er zum Zeitpunkt der Verzögerung ausgewertet wurde.
Um dieses Problem zu beheben, haben wir kann eine anonyme Funktion innerhalb der „defer“-Anweisung verwenden:
defer func() { fmt.Println(x) }()
Hier ist x kein Parameter der anonymen Funktion, daher wird es nicht ausgewertet, wenn die „defer“-Anweisung wird ausgeführt. Stattdessen wird der Wert von x zum Zeitpunkt des Aufrufs der anonymen Funktion erfasst, um sicherzustellen, dass der aktuellste Wert gedruckt wird.
Verwendung eines Zeigers:
var x int defer func() { fmt.Println(&x) }()
Dieser Ansatz verwendet einen Zeiger auf x als Parameter der verzögerten Funktion. Wenn die „defer“-Anweisung ausgeführt wird, wird nur der Zeiger ausgewertet, nicht der Wert von x. Wenn die verzögerte Funktion aufgerufen wird, greift sie über den Zeiger auf den aktuellen Wert von x zu.
Verwenden eines benutzerdefinierten Typs:
type MyInt int func (m *MyInt) String() string { return strconv.Itoa(int(*m)) } var x MyInt defer fmt.Println(&x)
Diese Lösung ähnelt dem Zeigeransatz, verwendet jedoch einen benutzerdefinierten Typ (MyInt), der die String()-Methode implementiert. Durch die Implementierung von String() können wir steuern, wie der Wert von ein Deskriptortyp in Go, was bedeutet, dass sein Wert eine Referenz auf ein zugrunde liegendes Array ist. Wenn wir einen Slice verschieben, wird nur die Referenz ausgewertet, nicht die tatsächlichen Array-Elemente. Infolgedessen werden alle Änderungen, die nach der Verschiebung an den Slice-Elementen vorgenommen werden, in der gedruckten Ausgabe widergespiegelt.
Umschließen in einer Struktur:
var x []int defer fmt.Println(x)
Dieser Ansatz ähnelt der Verwendung eines Zeigers, aber wir packen den Wert in eine Struktur ein, um zu vermeiden, dass der Zeiger im Deferred dereferenziert werden muss Funktion.
Das obige ist der detaillierte Inhalt vonWie verwende ich „defer' in Go mit geänderten Variablen richtig?. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!