Das Schlüsselwort defer in Go verschiebt die Ausführung der angegebenen Funktionen bis zum Verlassen der umgebenden Funktion – die Funktionen werden im Stack gespeichert und in umgekehrter Reihenfolge (LIFO) ausgeführt. Dies wird häufig zum Freigeben von Ressourcen (Dateien, Mutex, Verbindungen) verwendet.
Eine Besonderheit ist, dass alle Argumente der Funktionen, die in defer übergeben werden, sofort zum Zeitpunkt der Deklaration berechnet werden und nicht bei der Ausführung.
func test() { for i := 0; i < 3; i++ { defer fmt.Println(i) // Gibt aus: 2, 1, 0 } }
Was gibt der folgende Code aus?
func main() { for i := 0; i < 3; i++ { defer fmt.Println(i) } }
Antwort:
Das gibt aus:
2
1
0
Weil das Argument i bei jeder Schleife sofort (zum Zeitpunkt von defer) berechnet wird und alle Werte im defer-Stack gespeichert werden.
Geschichte
Im Dateidienst wurde vergessen zu berücksichtigen, dass defer nur bei normalem Verlassen der Funktion aufgerufen wird. Es traten Lecks auf, wenn das Programm vor dem Aufruf von defer abstürzte.
Geschichte
In der Datenpipeline gab es ein Vergessen – im Loop wurde defer zum Schließen von Verbindungen verwendet, tatsächlich wurden sie jedoch erst nach Abschluss der gesamten Funktion geschlossen und nicht nach jeder Iteration. Dies führte zu Ressourcenerschöpfung.
Geschichte
Im Logger wurde defer mit einer anonymen Funktion verwendet, in der Annahme, dass das Argument zum Zeitpunkt des Aufrufs berechnet wird. Dadurch enthielt das Log am Ende veraltete Informationen, da die Werte zuvor erfasst wurden.