En Go, el enfoque estándar es el manejo de errores a través del valor devuelto error. Esto permite controlar explícitamente qué hacer cuando ocurre un error en cada punto. Panic es un mecanismo para manejar situaciones catastróficas imprevistas: interrumpe la ejecución hasta el defer más cercano, donde se puede utilizar recover para "salvar". Pero recover solo funciona dentro de defer.
Mejores prácticas:
func safeDivide(a, b int) (int, error) { if b == 0 { return 0, errors.New("divide by zero") } return a/b, nil } func mustDivide(a, b int) int { if b == 0 { panic("divide by zero!") } return a/b }
¿Se puede "capturar" cualquier error de pánico con recover en cualquier parte del programa?
Respuesta: No, recover solo funcionará dentro de defer y solo en la misma goroutine donde se produce el pánico. En otros casos, el pánico terminará la ejecución de esta (o todas) las goroutines, lo cual a menudo es inesperado.
Historia
En la API REST se usó panic para manejar errores comunes en la lógica de negocios. Esto llevó a caídas no evidentes de la aplicación y registros incorrectos, porque recover no funcionaba correctamente en todos los casos.
Historia
En el servicio de procesamiento de pagos se implementó defer + recover en la función principal para "capturar" todos los pánicos, pero se olvidaron de las goroutines: en las goroutines hijas, sin defer/recover, la aplicación caía con errores "horribles", dejando algunas transacciones en un estado inconsistente.
Historia
En el analizador de estructuras complejas se olvidó devolver un error, se reemplazó por panic: esto complicó el mantenimiento y las pruebas, y se tuvo que reescribir completamente el manejo de errores para tener un registro detallado y una experiencia de usuario correcta.