¿Por qué Go no tiene Try-Catch?
Go no admite intencionalmente try-catch, y solo admite la sintaxis panic-recover. Esto está generando el descontento de muchos desarrolladores que están acostumbrados al manejo de errores mediante try-catch. Entonces, ¿por qué no incluir try-catch? Esto se debe a que try-catch tiene varios problemas.
try-catch-finally
La construcción try-catch es una sintaxis para manejar situaciones de error y situaciones excepcionales que pueden ocurrir durante la ejecución del programa (tiempo de ejecución). Además, la construcción finally se utiliza para escribir código que debe ejecutarse incondicionalmente, independientemente de si se produce una excepción o no.
Manejo de errores y responsabilidad
En los años 80 y 90, el manejo de errores era muy simple. Los mensajes de error eran solo 'Disquete lleno', 'No hay disquete en la unidad' y 'No hay permiso para escribir en el disquete'. En esa época, cuando ocurría un error, los desarrolladores lanzaban el error hasta el punto de manejo de errores para un tratamiento común. En esta situación, la construcción try-catch funcionaba de manera eficiente.
Sin embargo, con el tiempo, la situación cambió. La lógica de negocios se volvió compleja, surgieron las bases de datos y las transacciones, y hubo que interpretar numerosos mensajes de solicitud al llamar a numerosas API a través de la red. Incluso, con la aparición de la programación concurrente, se tuvo que manejar errores en otros hilos que no eran el hilo principal.
Los errores se volvieron tan complejos que ya no podían ser manejados en un solo lugar, y ninguna ubicación podía ser responsable de todos los errores. Aquí es donde surge un grave problema con el try-catch.
Transferencia de responsabilidad de try-catch
En resumen, try-catch es una forma en la que la entidad que generó un error transfiere la responsabilidad (seguimiento) de la ocurrencia del error a otra persona. El objetivo de la transferencia puede ser la construcción catch, su método padre, el padre de su padre, el padre del padre de su padre... puede ser cualquiera. En otras palabras, en un mundo donde el manejo de errores es cada vez mayor y más complejo, el método elegido por try-catch es simplemente "alguien lo hará". Observemos el siguiente código.
1try {
2 data = readFile("hello.txt");
3 structuredData = parseData(data);
4 insertDBStatus(structuredData[1]);
5 startHTTPServer(structuredData[2]);
6} catch (Exception e) {
7 e.printStackTrace();
8}
El problema con el código anterior es que no está claro quién es responsable de manejar printStackTrace, y tampoco se sabe en qué código ocurrió el error. Incluso, cuanto más lógica se agregue a la declaración try, peor será el problema. Sin embargo, paradójicamente, a medida que el desarrollo se vuelve más complejo, los desarrolladores se han vuelto adictos a la construcción try-catch que transfiere la responsabilidad, no se preocupan por el manejo de errores, la conciencia de responsabilidad también se ha desvanecido y, al final, han olvidado la esencia del manejo de errores y excepciones. Entonces, ¿cómo resolvió este problema golang?
panic, recover
Una de las ventajas de Go es que tiene varios sistemas para convertir a los desarrolladores en buenos desarrolladores, sin llevarlos por el mal camino. panic-recover también es un ejemplo de ello.
A primera vista, panic y recover no parecen diferentes de try-catch, pero la diferencia radica en que no transfieren la responsabilidad al exterior cuando surge un problema. Cuando se produce un panic en Go, en lugar de devolver el valor al exterior, se debe resolver en la ubicación donde se produjo el panic. Esto otorga a los desarrolladores la responsabilidad del manejo de errores y los induce a pensar más profundamente dónde, quién y cómo deben manejar el error. Es una forma de garantizar la autonomía del usuario, dejando al mismo tiempo espacio para la reflexión.
Además, la selección de la palabra panic es excelente. A diferencia de try-recover, panic-recover impone a los desarrolladores la presión, solo por las palabras, de que debe utilizarse solo en situaciones de error evidentes, no en situaciones excepcionales. Naturalmente, los desarrolladores no abusan de recover y lo utilizan solo donde es necesario. Esto ayuda mucho a escribir código conciso en Go.