Utiliser `recover`
Fait partie de la section Logique & Flux du Journey GO de Coddy — leçon 43 sur 68.
Alors que panic arrête votre programme immédiatement, Go offre un moyen de reprendre le contrôle via la fonction recover. La fonction recover vous permet de capturer une panique et de la gérer proprement, empêchant ainsi l'intégralité de votre programme de planter.
Cependant, recover a une exigence très spécifique : il ne peut être utilisé qu'à l'intérieur d'une fonction différée. Lorsqu'une panique survient, Go exécute toutes les fonctions différées avant que le programme ne se termine, donnant à recover une chance d'intercepter la panique :
func riskyFunction() {
defer func() {
if r := recover(); r != nil {
fmt.Println("Recovered from panic:", r)
}
}()
panic("something went wrong!")
}La fonction recover retourne la valeur qui a été passée à panic, ou nil si aucune panique ne s'est produite. Cela vous permet de vérifier si une panique s'est produite et de prendre les mesures appropriées, comme journaliser l'erreur ou effectuer des opérations de nettoyage.
Tout comme panic, recover doit être utilisé avec parcimonie en Go. On le rencontre le plus souvent dans des scénarios tels que les serveurs web, où l'on souhaite empêcher le panic d'une seule requête de faire planter l'ensemble du serveur, lui permettant ainsi de continuer à traiter d'autres requêtes.
Cette leçon comprend un petit quiz. Commencez la leçon pour y répondre et suivre votre progression.
Cette leçon comprend un petit quiz. Commencez la leçon pour y répondre et suivre votre progression.
Cette leçon comprend un petit quiz. Commencez la leçon pour y répondre et suivre votre progression.
Défi
FacileCréez un gestionnaire de requêtes de serveur web qui utilise recover pour gérer gracieusement les paniques et empêcher le serveur entier de s'arrêter. Ce défi démontre comment utiliser recover à l'intérieur d'une fonction différée (deferred function) pour intercepter les paniques et maintenir la stabilité du serveur.
Vous recevrez deux entrées :
- Une chaîne contenant les détails de la requête au format
"endpoint,method,action"(par exemple,"/api/users,GET,process") - Une chaîne contenant la configuration du serveur au format
"server_name,max_requests"(par exemple,"WebServer,100")
Votre tâche consiste à :
- Analyser la première entrée en la divisant par les virgules pour obtenir l'endpoint, la méthode et l'action
- Analyser la deuxième entrée en la divisant par les virgules pour obtenir le nom du serveur et le nombre maximum de requêtes
- Convertir la chaîne du nombre maximum de requêtes en un entier
- Créer une fonction nommée
handleRequestqui prend l'endpoint, la méthode, l'action et le nom du serveur comme paramètres - À l'intérieur de
handleRequest, ajouter une fonction différée (deferred function) qui utiliserecoverpour intercepter toute panique :- Si une panique est récupérée (recover renvoie une valeur non nulle), affichez :
"Server [server_name] recovered from panic: [panic_value]" - Après avoir géré la panique, affichez :
"Request handling completed safely"
- Si une panique est récupérée (recover renvoie une valeur non nulle), affichez :
- Après la fonction différée, simulez le traitement de la requête en fonction de l'action :
- Si l'action est
"process": affichez"Processing [method] request to [endpoint]" - Si l'action est
"panic_nil": affichez"Attempting dangerous operation"puis appelezpanic("nil pointer access") - Si l'action est
"panic_overflow": affichez"Attempting resource allocation"puis appelezpanic("memory overflow") - Si l'action est
"panic_timeout": affichez"Attempting database connection"puis appelezpanic("connection timeout") - Pour toute autre action : affichez
"Unknown action: [action]"puis appelezpanic("invalid action")
- Si l'action est
- Dans la fonction principale, affichez le message de démarrage du serveur :
"Starting [server_name] with max [max_requests] requests" - Appelez la fonction
handleRequestavec les paramètres analysés - Après l'appel de la fonction, affichez l'état du serveur :
"Server [server_name] is still running" - Enfin, affichez un résumé :
"Server Summary:""Name: [server_name]""Max Requests: [max_requests]""Last Request: [method] [endpoint]""Action Performed: [action]""Status: Operational"
Utilisez le package strings pour diviser les chaînes d'entrée sur les virgules et le package strconv pour convertir la chaîne du nombre maximum de requêtes en un entier. Ce défi démontre comment recover permet aux serveurs de gérer les paniques inattendues de manière gracieuse, empêchant les échecs de requêtes individuelles de faire tomber l'ensemble du système.
Aide-mémoire
La fonction recover vous permet de capturer un panic et de le gérer proprement, empêchant ainsi votre programme de planter.
recover ne peut être utilisé qu'à l'intérieur d'une fonction différée (deferred) :
func riskyFunction() {
defer func() {
if r := recover(); r != nil {
fmt.Println("Recovered from panic:", r)
}
}()
panic("something went wrong!")
}La fonction recover renvoie la valeur qui a été transmise à panic, ou nil si aucun panic ne s'est produit. Cela vous permet de vérifier si un panic a eu lieu et de prendre les mesures appropriées.
recover est couramment utilisé dans les serveurs web pour empêcher le panic d'une seule requête de faire planter l'ensemble du serveur.
Essayez vous-même
package main
import (
"fmt"
"strconv"
"strings"
)
func main() {
// Lire l'entrée
var requestDetails string
var serverConfig string
fmt.Scanln(&requestDetails)
fmt.Scanln(&serverConfig)
// Analyser les détails de la requête
requestParts := strings.Split(requestDetails, ",")
endpoint := requestParts[0]
method := requestParts[1]
action := requestParts[2]
// Analyser la configuration du serveur
configParts := strings.Split(serverConfig, ",")
serverName := configParts[0]
maxRequests, _ := strconv.Atoi(configParts[1])
// TODO: Écrivez votre code ci-dessous
// Créer la fonction handleRequest avec un mécanisme de récupération (recover)
// Afficher le message de démarrage du serveur
// Appeler la fonction handleRequest
// Afficher l'état du serveur et le résumé
}Cette leçon comprend un petit quiz. Commencez la leçon pour y répondre et suivre votre progression.
Toutes les leçons de Logique & Flux
1Structures de contrôle avancées
Switch avec `fallthrough`Sortir de boucles imbriquéesContinuer une boucle spécifiqueL'instruction `goto`Récapitulatif - Contrôle de boucle avancé4Projet : Liste de tâches simple
Configuration du projetAjouter une tâche7Gestion des erreurs en profondeur
Types d'erreurs personnalisésEnvelopper des erreurs avec `%w`Désenvelopper avec `errors.Is`Désenvelopper avec `errors.As`Comprendre `panic`Utiliser `recover`Récapitulatif - Division sécurisée2Structures et Méthodes
Définir des méthodes sur des structuresReceveurs par valeurReceveurs par pointeurChoisir les receveursMéthodes vs FonctionsRécapitulatif - Comportement des structures5Les Maps en profondeur
Maps de StructsPointeurs comme valeurs de MapTester les Maps NilComparer des MapsRécapitulatif - Compteur de fréquence de mots3Interfaces (Les bases)
Qu'est-ce qu'une Interface ?Définir une InterfaceImplémenter une InterfaceUtiliser les types d'InterfaceInterface videAssertions de typeType SwitchRécapitulatif - Formes et comportements