Leçons du module (5/5)
defer : nettoyage garanti
defer reporte l'exécution d'un appel jusqu'à la fonction englobante
renvoie. Il s'exécute même si la fonction se termine par panique. Plusieurs defer
dans la même fonction, exécutez dans l'ordre LIFO (Dernier entré, Premier sorti).
C'est le mécanisme idiomatique du nettoyage des ressources : fermer les fichiers, déverrouiller les mutex, libérer les connexions, restaurer l'état.
Syntaxe et cas d'utilisation canonique
f, err := os.Open(path)
if err != nil {
return err
}
defer f.Close() // chiamata SEMPRE all'uscita della funzione
// ... usa f liberamente ...
return nilTypique : f.Close(), mu.Unlock(), db.Close(), tx.Rollback(),
recover().
Arguments évalués immédiatement, exécution reportée
Lorsque vous écrivez defer foo(x), x est évalué au moment de la
defer, pas au moment de l'exécution :
x := 10
defer fmt.Println(x) // cattura 10
x = 99
// quando la funzione ritorna stampa "10", non "99"## Ordre LIFO
Les reports s'empilent et s'exécutent en commençant par le plus récent :
defer fmt.Println(1)
defer fmt.Println(2)
defer fmt.Println(3)
// output: 3, 2, 1Ceci est cohérent avec la sémantique des ressources : la dernière ouverte est la première être fermé.
defer + recover : gestion de la panique
defer est le seul moyen d'intercepter un panic :
func safe() {
defer func() {
if r := recover(); r != nil {
fmt.Println("recuperato:", r)
}
}()
panic("boom")
}Piège : defer en boucle
Mettre defer f.Close() dans une boucle accumule des reports jusqu'à la fin de
la fonction, pas de chaque itération. Dans une longue boucle, vous ouvrez de nombreux fichiers
et ne les fermez qu'à la sortie de la fonction : risque de fuite du descripteur de fichier.
// MALE: defer accumulati
for _, path := range paths {
f, _ := os.Open(path)
defer f.Close() // chiude TUTTI alla fine della funzione esterna
// ...
}
// MEGLIO: estrai in una funzione
for _, path := range paths {
elabora(path) // ogni chiamata ha il proprio scope di defer
}Essayez-le
Imprimez 'inizio', puis différez l'impression de 'fine' avec defer, puis imprimez 'mezzo'. La sortie doit être : inizio / mezzo / fine.
Afficher l'indice
Le defer s'exécute lorsque main() est sur le point de revenir.
Solution disponible après 3 tentatives
Écrivez trois reports consécutifs qui impriment 1, 2 et 3 dans cet ordre dans le code. La sortie sera 3/2/1 (LIFO).
Afficher l'indice
Trois reports en séquence ; rappelez-vous qu'ils s'exécutent dans l'ordre inverse.
Solution disponible après 3 tentatives
Qu'est-ce que cela imprime ? (remarque : les arguments de report sont évalués immédiatement)
x := 10
defer fmt.Println(x)
x = 99Récapitulatif
defer call()reporte l'exécution jusqu'au retour de la fonction.- Plusieurs reports = ordre LIFO.
- Arguments évalués immédiatement, exécution reportée.
- Utilisé pour le nettoyage déterministe : fichiers, mutex, connexions.
defer+recover()intercepte unpanic(rare, aux frontières).- Jamais
deferà l'intérieur d'une longue boucle : il s'accumule jusqu'au retour de la fonction externe.