ProgrammationDéveloppeur Go Senior

Parlez-nous de la façon dont Go implémente les fonctions intégrées recover et panic. Quel est l'ordre correct de leur utilisation pour une récupération sûre dans une goroutine ?

Réussissez les entretiens avec l'assistant IA Hintsage

Réponse

Dans Go, la panique (panic) est utilisée pour signaler une erreur fatale dans le programme. Après l'appel de panic, l'exécution commence par le dévouement de la pile et l'appel de toutes les fonctions différées (deferred). S'il y a une fonction dans la pile avec un appel à recover(), elle peut intercepter et traiter la panique — mais recover ne fonctionne que dans sa propre goroutine et seulement lorsqu'il est appelé depuis defer.

Le modèle recommandé pour une récupération sûre :

func safe(fn func()) { defer func() { if r := recover(); r != nil { fmt.Println("Récupéré de la panique :", r) } }() fn() } go safe(func() { panic("échec !") // ne provoque pas l'arrêt du programme })

Il est important de se souvenir que :

  • panic termine l'exécution de la goroutine en cours jusqu'à la première récupération
  • Recover fonctionne uniquement lorsqu'il est appelé depuis defer au sein de la même goroutine
  • Si recover n'est pas utilisé, la panique entraînera l'arrêt de l'ensemble du programme

Question piège

Recover peut-il intercepter une panique survenue dans une autre goroutine ?

Réponse : Non, recover ne fonctionne que dans la goroutine où la panique s'est produite, et seulement s'il est appelé dans une fonction deferred. Si la panique se produit dans une goroutine et que recover est appelé dans une autre — l'interception ne se produira pas, le programme échouera.

Exemple :

func main() { go func() { panic("dans la goroutine") }() time.Sleep(time.Second) recover() // Ne fonctionnera pas ! Panic arrêtera le programme }

Exemples d'erreurs réelles dues à l'ignorance des subtilités du sujet


Histoire

Un développeur a implémenté le traitement des erreurs en utilisant le modèle defer recover() uniquement dans la fonction principale. Lorsque la panique s'est produite à l'intérieur d'un worker dans une goroutine séparée, tout le programme a échoué — l'erreur n'a pas été interceptée par le recover global.


Histoire

Dans le projet, ils ont utilisé defer/recover pour un arrêt gracieux du serveur Web, pensant que c'était suffisant. Il s'est avéré que la panique dans l'une des goroutines a terminé tout le processus, car le traitement de recover était mal placé — il a fallu refactoriser tout le pool de workers.


Histoire

Dans le flux de traitement des messages, une panique est survenue à cause d'un mauvais fonctionnement de la fonction utilisateur. Le développeur s'attendait à ce que son "attrape" recover de niveau supérieur, mais n'a pas réalisé que recover ne fonctionne QUE depuis defer. En conséquence, le service s'est écrasé de manière irrégulière lorsque des messages incorrects apparaissaient dans la file d'attente.