panic, recover et defer
Savoir quand déclencher panic et comment récupérer proprement
panic, recover et defer est une leçon Go Academy gratuite sur CoddyKit. Ceci est la leçon 4 sur 4. Tu peux lire la leçon complète ci-dessous gratuitement — puis la pratiquer en direct dans le navigateur avec un éditeur de code intégré et un tuteur IA 24/7. Elle fait partie du parcours d'apprentissage Go Academy, et ta progression se synchronise sur le web et l'application CoddyKit. Le cours Go Academy comprend 4 leçons au total.
Qu'est-ce que panic ?
panic arrête l'exécution normale de la goroutine actuelle, remonte la pile d'appels en exécutant les fonctions différées et provoque l'arrêt du programme si la panique n'est pas récupérée :
package main
import "fmt"
func mustPositive(n int) int {
if n <= 0 {
panic(fmt.Sprintf("mustPositive: got %d", n))
}
return n
}
func main() {
fmt.Println(mustPositive(5)) // 5
// fmt.Println(mustPositive(-1)) // panics!
}Quand utiliser panic
Utilisez panic uniquement pour :
- Les erreurs de programmation véritablement irrécupérables (invariants rompus)
- Les conditions impossibles qui indiquent un bogue
- Les échecs au démarrage (configuration manquante, connexions échouées lors de l'initialisation)
N'utilisez jamais panic pour les conditions d'échec attendues — utilisez plutôt error.
Notions de base de defer
defer planifie l'appel d'une fonction au moment où la fonction englobante retourne, quelle que soit la manière dont elle retourne (normalement, avec une erreur ou à la suite d'une panique) :
package main
import "fmt"
func main() {
defer fmt.Println("third")
defer fmt.Println("second") // LIFO order
defer fmt.Println("first")
fmt.Println("running...")
// Output:
// running...
// first
// second
// third
}defer pour le nettoyage
L'utilisation la plus courante de defer consiste à garantir le nettoyage des ressources :
package main
import ("fmt"; "os")
func readFile(path string) (string, error) {
f, err := os.Open(path)
if err != nil {
return "", fmt.Errorf("open: %w", err)
}
defer f.Close() // always runs, even if we return early
buf := make([]byte, 1024)
n, _ := f.Read(buf)
return string(buf[:n]), nil
}recover — intercepter les paniques
recover arrête une panique et retourne sa valeur. Il doit être appelé directement dans une fonction defer :
package main
import "fmt"
func safeDiv(a, b int) (result int, err error) {
defer func() {
if r := recover(); r != nil {
err = fmt.Errorf("recovered from panic: %v", r)
}
}()
return a / b, nil // panics if b==0
}
func main() {
r, err := safeDiv(10, 0)
fmt.Println(r, err)
// 0 recovered from panic: runtime error: integer divide by zero
}recover doit se trouver dans une fonction différée
recover ne fonctionne que s'il est appelé directement dans une fonction différée. Un appel effectué ailleurs retourne nil :
package main
import "fmt"
func wrong() {
// recover() here does nothing — not in defer
}
func correct() {
defer func() {
if r := recover(); r != nil {
fmt.Println("caught:", r)
}
}()
panic("oops")
}
func main() { correct() }panic dans le code de bibliothèque
Le code de bibliothèque ne devrait presque jamais laisser des paniques parvenir aux appelants. Convertissez les paniques en erreurs à la limite de l'API :
package main
import ("fmt"; "runtime/debug")
func safeCall(fn func()) (err error) {
defer func() {
if r := recover(); r != nil {
err = fmt.Errorf("panic: %v\n%s", r, debug.Stack())
}
}()
fn()
return nil
}
func main() {
err := safeCall(func() { panic("boom") })
fmt.Println(err != nil) // true
}Ordre LIFO de defer et piège des boucles
Les appels différés s'exécutent dans l'ordre dernier entré, premier sorti (LIFO). Soyez prudent lorsque vous utilisez defer dans des boucles — utilisez une fermeture ou une fonction auxiliaire :
package main
import "fmt"
func processFiles(names []string) {
for _, name := range names {
name := name // capture loop variable
defer func() { fmt.Println("close:", name) }()
}
}
func main() {
processFiles([]string{"a.txt", "b.txt", "c.txt"})
// Output (LIFO): close: c.txt, close: b.txt, close: a.txt
}defer avec des valeurs de retour nommées
Les fonctions différées peuvent lire et modifier les valeurs de retour nommées — ce qui est utile pour annoter les erreurs :
package main
import "fmt"
func doWork() (err error) {
defer func() {
if err != nil {
err = fmt.Errorf("doWork: %w", err)
}
}()
return fmt.Errorf("something failed")
}
func main() {
err := doWork()
fmt.Println(err) // doWork: something failed
}panic ou error : guide de décision
Choisir entre panic et error :
- Utilisez error : échecs attendus (fichier introuvable, délai d'attente du réseau dépassé, entrée invalide)
- Utilisez panic : erreurs de programmation (accès à une carte nil, accès hors limites), états impossibles, échecs d'initialisation
- N'utilisez jamais panic au-delà des limites d'une API — les appelants ne peuvent pas le gérer
- Récupérez les paniques au niveau supérieur des goroutines dans les serveurs pour éviter les arrêts
Vérification rapide
Où faut-il appeler recover() pour intercepter une panique ?
Récapitulatif : panic, recover et defer
Résumé :
panic: déroule la pile, exécute les appels différés et fait planter le programme si la panique n’est pas récupéréedefer: s’exécute à la sortie d’une fonction (normalement, en cas d’erreur ou de panique), dans l’ordre LIFOrecover: arrête la panique et renvoie sa valeur ; doit se trouver dansdefer- Utilisez panic pour les erreurs de programmation, pas pour les échecs attendus
- Convertissez les paniques en erreurs aux limites de l’API
Apprends Go avec un tuteur IA — gratuit
Écris et exécute du vrai code dans ton navigateur, obtiens de l'aide instantanée d'un tuteur IA disponible 24h/24, et reprends là où tu t'es arrêté sur le web ou dans l'app.
- Cours
- 51
- Leçons
- 203
Questions Fréquemment Posées
La leçon « panic, recover et defer » est-elle gratuite ?
Oui — le texte complet de « panic, recover et defer » est gratuit à lire ici sur le web. Pour la pratiquer de manière interactive (un éditeur de code intégré et un tuteur IA 24/7) et déverrouiller le reste du cours Go Academy, passe à CoddyKit PRO. Le cours Go Academy comprend 4 leçons au total.
Qu'est-ce que j'apprendrai dans « panic, recover et defer » ?
Savoir quand déclencher panic et comment récupérer proprement Tu pratiques Go Academy avec du code pratique que tu exécutes directement dans le navigateur, et un tuteur IA 24/7 répond à tes questions au fur et à mesure que tu avances dans la leçon.
Dois-je avoir de l'expérience pour commencer Go Academy ?
Aucune expérience préalable n'est requise. Go Academy sur CoddyKit est structuré pour les débutants jusqu'aux apprenants avancés, donc tu peux commencer ici ou depuis le début et avancer à ton rythme. Ceci est la leçon 4 sur 4.
Combien de temps prend la leçon « panic, recover et defer » ?
La plupart des leçons CoddyKit prennent environ 5–10 minutes. Chacune est courte et interactive, tu progresses régulièrement et tu repiques exactement où tu t'es arrêté sur le web et l'app.
Peux-tu écrire et exécuter du code dans cette leçon Go Academy ?
Oui. Chaque leçon Go Academy inclut un éditeur de code intégré, tu écris et exécutes du vrai code directement dans ton navigateur et tu reçois des retours IA instantanés — aucune configuration locale requise.
Toutes les leçons de ce cours
- L’interface error
- Créer des erreurs personnalisées
- Encapsuler et désencapsuler les erreurs
- panic, recover et defer