En Go, el pánico (panic) se usa para señalar un error fatal en el programa. Después de llamar a panic, la ejecución comienza con el deslizamiento de la pila y la llamada a todas las funciones diferidas. Si hay una función en la pila que llama a recover(), puede capturar y manejar el pánico, pero recover solo funciona dentro de su goroutine y solo si se llama desde defer.
El patrón recomendado para una recuperación segura:
func safe(fn func()) { defer func() { if r := recover(); r != nil { fmt.Println("Recuperado del pánico:", r) } }() fn() } go safe(func() { panic("¡fallo!") // no detiene la ejecución del programa })
Es importante recordar que:
panic detiene la ejecución de la goroutine actual hasta el primer recover¿Puede recover capturar un pánico que ocurrió en otra goroutine?
Respuesta: No, recover solo funciona dentro de la goroutine donde ocurrió el pánico, y solo si se llama en una función diferida (defer). Si el pánico ocurrió en una goroutine y recover se llama en otra, no habrá captura, y el programa terminará abruptamente.
Ejemplo:
func main() { go func() { panic("dentro de la goroutine") }() time.Sleep(time.Second) recover() // ¡No funcionará! Panic terminará el programa }
Historia
Un desarrollador implementó el manejo de errores utilizando el patrón defer recover() solo en la función principal. Cuando ocurrió un pánico dentro de un worker en una goroutine separada, todo el programa terminó abruptamente, ya que el error no fue capturado por el recover global.
Historia
En el proyecto se utilizó defer/recover para un cierre limpio del servidor web, pensando que eso era suficiente. Resultó que un pánico en una de las goroutines de la lógica terminaba todo el proceso, porque el manejo de recover no estaba en el lugar correcto, lo que obligó a refactorizar todo el grupo de workers.
Historia
En el hilo de procesamiento de mensajes ocurrió un pánico debido a un mal funcionamiento de la función del usuario. El desarrollador esperaba que fuera "capturado" por el recover de alto nivel, pero no se dio cuenta de que recover funciona SOLAMENTE desde defer. Como resultado, el servicio se bloqueaba de manera irregular cuando un mensaje incorrecto aparecía en la cola.