Uso de `recover`
Parte de la sección Lógica y Flujo del Journey de GO de Coddy — lección 43 de 68.
Mientras que panic detiene tu programa inmediatamente, Go proporciona una forma de recuperar el control a través de la función recover. La función recover te permite capturar un pánico y manejarlo de forma elegante, evitando que todo tu programa se bloquee.
Sin embargo, recover tiene un requisito muy específico: solo puede usarse dentro de una función diferida. Cuando ocurre un pánico, Go ejecuta todas las funciones diferidas antes de que el programa finalice, dándole a recover la oportunidad de interceptar el pánico:
func riskyFunction() {
defer func() {
if r := recover(); r != nil {
fmt.Println("Recovered from panic:", r)
}
}()
panic("something went wrong!")
}La función recover devuelve el valor que se pasó a panic, o nil si no ocurrió ningún pánico. Esto le permite comprobar si ocurrió un pánico y tomar las medidas adecuadas, como registrar el error o realizar operaciones de limpieza.
Al igual que panic, recover debe usarse con moderación en Go. Se ve con mayor frecuencia en escenarios como servidores web donde se desea evitar que el pánico de una sola solicitud bloquee todo el servidor, permitiéndole continuar atendiendo otras solicitudes.
Esta lección incluye un breve cuestionario. Empieza la lección para responderlo y registrar tu progreso.
Esta lección incluye un breve cuestionario. Empieza la lección para responderlo y registrar tu progreso.
Esta lección incluye un breve cuestionario. Empieza la lección para responderlo y registrar tu progreso.
Desafío
FácilCrea un manejador de solicitudes de servidor web que utilice recover para gestionar de forma segura los pánicos (panics) y evitar que todo el servidor se bloquee. Este desafío demuestra cómo usar recover dentro de una función diferida (deferred function) para capturar pánicos y mantener la estabilidad del servidor.
Recibirás dos entradas:
- Una cadena que contiene los detalles de la solicitud en el formato
"endpoint,method,action"(por ejemplo,"/api/users,GET,process") - Una cadena que contiene la configuración del servidor en el formato
"server_name,max_requests"(por ejemplo,"WebServer,100")
Tu tarea es:
- Analizar la primera entrada dividiéndola por comas para obtener el endpoint, method y action
- Analizar la segunda entrada dividiéndola por comas para obtener el server name y max requests
- Convertir la cadena de max requests a un entero
- Crear una función llamada
handleRequestque tome endpoint, method, action y server name como parámetros - Dentro de
handleRequest, añade una función diferida que utilicerecoverpara capturar cualquier pánico:- Si se recupera un pánico (recover devuelve un valor no nulo), imprime:
"Server [server_name] recovered from panic: [panic_value]" - Después de manejar el pánico, imprime:
"Request handling completed safely"
- Si se recupera un pánico (recover devuelve un valor no nulo), imprime:
- Después de la función diferida, simula el procesamiento de la solicitud basándote en la acción:
- Si action es
"process": imprime"Processing [method] request to [endpoint]" - Si action es
"panic_nil": imprime"Attempting dangerous operation"y luego llama apanic("nil pointer access") - Si action es
"panic_overflow": imprime"Attempting resource allocation"y luego llama apanic("memory overflow") - Si action es
"panic_timeout": imprime"Attempting database connection"y luego llama apanic("connection timeout") - Para cualquier otra acción: imprime
"Unknown action: [action]"y luego llama apanic("invalid action")
- Si action es
- En la función main, imprime el mensaje de inicio del servidor:
"Starting [server_name] with max [max_requests] requests" - Llama a la función
handleRequestcon los parámetros analizados - Después de la llamada a la función, imprime el estado del servidor:
"Server [server_name] is still running" - Finalmente, imprime un resumen:
"Server Summary:""Name: [server_name]""Max Requests: [max_requests]""Last Request: [method] [endpoint]""Action Performed: [action]""Status: Operational"
Utiliza el paquete strings para dividir las cadenas de entrada por comas y el paquete strconv para convertir la cadena de max requests a un entero. Este desafío demuestra cómo recover permite a los servidores manejar pánicos inesperados con elegancia, evitando que los fallos en solicitudes individuales derriben todo el sistema.
Hoja de referencia
La función recover te permite capturar un pánico y manejarlo de forma controlada, evitando que tu programa se cierre inesperadamente.
recover solo puede utilizarse dentro de una función diferida (deferred):
func riskyFunction() {
defer func() {
if r := recover(); r != nil {
fmt.Println("Recovered from panic:", r)
}
}()
panic("something went wrong!")
}La función recover devuelve el valor que se pasó a panic, o nil si no ocurrió ningún pánico. Esto te permite comprobar si ocurrió un pánico y tomar las medidas adecuadas.
recover se utiliza comúnmente en servidores web para evitar que el pánico de una sola solicitud provoque la caída de todo el servidor.
Pruébalo tú mismo
package main
import (
"fmt"
"strconv"
"strings"
)
func main() {
// Leer entrada
var requestDetails string
var serverConfig string
fmt.Scanln(&requestDetails)
fmt.Scanln(&serverConfig)
// Analizar detalles de la solicitud
requestParts := strings.Split(requestDetails, ",")
endpoint := requestParts[0]
method := requestParts[1]
action := requestParts[2]
// Analizar configuración del servidor
configParts := strings.Split(serverConfig, ",")
serverName := configParts[0]
maxRequests, _ := strconv.Atoi(configParts[1])
// TODO: Escribe tu código a continuación
// Crear la función handleRequest con mecanismo de recuperación (recover)
// Imprimir mensaje de inicio del servidor
// Llamar a la función handleRequest
// Imprimir el estado del servidor y el resumen
}Esta lección incluye un breve cuestionario. Empieza la lección para responderlo y registrar tu progreso.
Todas las lecciones de Lógica y Flujo
1Flujo de control avanzado
Switch con `fallthrough`Salir de bucles anidadosContinuar un bucle específicoLa sentencia `goto`Repaso: Control de bucles avanzado4Proyecto: Lista de tareas sencilla
Configuración del proyectoAñadir una tarea7Manejo de errores a fondo
Tipos de error personalizadosEnvolver errores con `%w`Desenvolver con `errors.Is`Desenvolver con `errors.As`Entendiendo `panic`Uso de `recover`Repaso - División segura2Estructuras y Métodos
Definición de métodos en estructurasReceptores de valorReceptores de punteroElegir receptoresMétodos vs FuncionesResumen - Comportamiento de estructuras5Mapas en profundidad
Mapas de StructsPunteros como valores de MapVerificación de Maps NilComparación de MapsResumen - Contador de frecuencia de palabras3Interfaces (Conceptos básicos)
¿Qué es una interfaz?Definir una interfazImplementar una interfazUso de tipos de interfazInterfaz vacíaAserciones de tipoType SwitchResumen: Formas y comportamientos