ProgramaciónDesarrollador Senior de Go

Cuéntame cómo Go implementa las funciones integradas recover y panic. ¿Cuál es el orden correcto para su uso para una recuperación segura en goroutine?

Supere entrevistas con el asistente de IA Hintsage

Respuesta

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
  • Recover solo funciona si se llama desde defer dentro de la misma goroutine
  • Si no se usa recover, el pánico llevará a la terminación de todo el programa

Pregunta trampa

¿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 }

Ejemplos de errores reales debido a la falta de conocimiento sobre los matices del tema


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.