Vol. 4 — № 03
The Go Loop · KiosqueNewsstand
Blog  
Un atelier Go · Édition d'ApprentissageA Go Workshop · Learning Edition

panic / recover, la frontière panic / recover, the boundary

panic n'est pas un try/catch : on panique quand un invariant est rompu, pas pour une erreur attendue. recover ne se pose qu'à la lisière — une requête, une goroutine — et un panic non rattrapé emporte tout le process. panic isn't a try/catch: you panic when an invariant breaks, not for an expected error. recover sits only at the boundary — a request, a goroutine — and an uncaught panic takes the whole process down.

AudienceAudience
Dev tenté d'utiliser panic/recover comme un try/catch, surpris qu'une goroutine non gardée tue tout Dev tempted to use panic/recover as a try/catch, surprised an unguarded goroutine kills everything
Format
Self-paced
ChapitresChapters
5
Date
Mai 2027 May 2027
≈ 16 min ●●●○ panicrecoverInvariants

Chapitre 1 en accès libre — la suite (ch. 2 à 5) est réservée. Chapter 1 free to read — the rest (ch. 2–5) is members-only.

№ 01CadrageFraming3 min

panic n'est pas le try/catch de Go. C'est la ligne où la valeur cesse.panic isn't Go's try/catch. It's the line where the value stops.

Tout le volume a tenu une promesse : l'échec est une valeur qu'on rend, qu'on teste, qu'on enveloppe. panic semble la rompre — il déroule la pile, saute par-dessus le code, ressemble à s'y méprendre à l'exception qu'on disait absente. C'est un piège de lecture. panic et error ne sont pas deux outils pour le même travail ; ils répondent à deux registres incompatibles. Une error est un échec attendu : le fichier manquant, la connexion perdue, l'entrée malformée. Le programme a prévu ce cas, et l'appelant peut décider quoi en faire. Un panic est un échec impossible : un invariant rompu, un état qui ne devait jamais exister, un bug du programme contre lui-même. Là, il n'y a rien à décider — l'appelant ne peut pas « gérer » un programme devenu incohérent. La règle tient en une question : est-ce une situation que le code aurait dû anticiper, ou la preuve qu'il est déjà cassé ? La première se rend. La seconde panique.The whole volume kept one promise: failure is a value you return, test, wrap. panic seems to break it — it unwinds the stack, leaps over code, looks exactly like the exception we said was absent. That's a reading trap. panic and error aren't two tools for the same job; they answer two incompatible registers. An error is an expected failure: the missing file, the lost connection, the malformed input. The program planned for this case, and the caller can decide what to do. A panic is an impossible failure: a broken invariant, a state that should never have existed, a bug of the program against itself. There, there's nothing to decide — the caller can't 'handle' a program gone incoherent. The rule fits in one question: is this a situation the code should have anticipated, or proof that it's already broken? The first is returned. The second panics.

L'échec attendu : une valeur que l'appelant gèreThe expected failure: a value the caller handles
// échec ATTENDU : le fichier peut ne pas exister. C'est une valeur.
f, err := os.Open(path)
if err != nil {
    return nil, fmt.Errorf("open %s: %w", path, err)   // on REND l'erreur
}
// l'appelant DÉCIDE : réessayer, valeur par défaut, abandonner.
L'échec impossible : un invariant rompu, on s'arrêteThe impossible failure: a broken invariant, you stop
// échec IMPOSSIBLE : cet index est censé être valide, toujours.
// s'il ne l'est pas, c'est un BUG du programme, pas une entrée invalide.
i := id % len(s.shards)        // invariant : i est forcément dans les bornes
shard := s.shards[i]
if shard == nil {
    panic("shard nil : invariant rompu")   // rien à RENDRE — on STOPPE
}
// personne ne peut « gérer » un programme incohérent avec lui-même.
Deux registres, jamais interchangeablesTwo registers, never interchangeable
error
échec attendu
l'appelant décide
|
panic
invariant rompu
le programme s'arrête

La frontière n'est pas technique, elle est sémantique : qui peut décider de la suite ? Si quelqu'un, en amont, peut raisonnablement réagir, c'est une error. Si la seule réponse sensée est « ce programme a un bug, arrête-toi », c'est un panic.The boundary isn't technical, it's semantic: who can decide what comes next? If someone, upstream, can reasonably react, it's an error. If the only sane answer is "this program has a bug, stop," it's a panic.

Le réflexe du numéroThe issue's reflex

« Une entrée invalide se rend ; un programme invalide panique. » Le débutant venu d'un langage à exceptions a le réflexe inverse : paniquer pour tout échec, rattraper partout. Le numéro défend la discipline opposée — panic est rare, réservé à l'irrécupérable : un index hors bornes, un nil qui ne devait jamais l'être, une assertion de programme. Pour tout le reste, il y a la valeur qu'on rend."Invalid input is returned; an invalid program panics." The beginner from an exception language has the opposite reflex: panic on every failure, catch everywhere. The issue argues the opposite discipline — panic is rare, reserved for the unrecoverable: an out-of-bounds index, a nil that should never have been, a program assertion. For everything else, there's the value you return.

Le runtime panique déjà pour toi.The runtime already panics for you.

Tu n'as souvent même pas besoin d'écrire panic : le runtime le fait à ta place quand un invariant fondamental casse. Accéder à un index hors bornes, déréférencer un pointeur nil, diviser par zéro, écrire dans une map nil — autant de panics levés par le langage lui-même. Ce ne sont pas des erreurs que tu aurais dû renvoyer : ce sont des bugs, signalés bruyamment plutôt que masqués. C'est cohérent avec tout le reste du langage : Go préfère un crash net, localisé, à un comportement indéfini qui pourrirait en silence. Quand tu écris panic toi-même, tu ne fais qu'étendre ce mécanisme à tes propres invariants.You often don't even need to write panic: the runtime does it for you when a fundamental invariant breaks. Indexing out of bounds, dereferencing a nil pointer, dividing by zero, writing to a nil map — all panics raised by the language itself. These aren't errors you should have returned: they're bugs, signaled loudly rather than hidden. It fits the rest of the language: Go prefers a clean, localized crash to undefined behavior rotting in silence. When you write panic yourself, you're just extending that mechanism to your own invariants.

🔒

La suite est réservée The rest is members-only

Le premier numéro est libre. Débloque tout The Go Loop — tous les volumes, à vie — pour 5 €, paiement unique. The first issue is free. Unlock all of The Go Loop — every volume, forever — for €5, one-time.

← Retour au kiosqueBack to newsstand