¿Alguien podría explicar las diferencias clave entre os.Exit()
y panic()
y cómo se utilizan en la práctica en Go?
En primer lugar, siempre que tenga una pregunta sobre "cómo se usa en la práctica", una buena manera de comenzar es buscar el código fuente de Go (o cualquier base de código de Go suficientemente grande, en realidad) y los documentos del paquete para obtener respuestas.
Ahora, os.Exit
y panic
son bastante diferentes. panic
se utiliza cuando el programa, o su parte, ha alcanzado un estado irrecuperable.
Cuando
panic
se llama, incluso implícitamente para errores de tiempo de ejecución como indexar un segmento fuera de los límites o fallar una afirmación de tipo, detiene inmediatamente la ejecución de la función actual y comienza a desenrollar la pila de goroutine, ejecutando cualquier función diferida en el camino. Si ese desenrollado alcanza la parte superior de la pila de goroutine, el programa muere.
os.Exit
se usa cuando necesita abortar el programa inmediatamente, sin posibilidad de recuperación o ejecutar una declaración de limpieza diferida, y también devuelve un código de error (que otros programas pueden usar para informar lo sucedido). Esto es útil en las pruebas, cuando ya sabe que después de que una de las pruebas falle, la otra también fallará, por lo que es mejor salir ahora. Esto también se puede usar cuando su programa ha hecho todo lo que tenía que hacer y ahora solo necesita salir, es decir, después de imprimir un mensaje de ayuda.
La mayoría de las veces no lo usará panic
(debe devolver un error
en su lugar), y casi nunca lo necesitará os.Exit
fuera de algunos casos en las pruebas y para la terminación rápida del programa.
exit
en ese caso, solo esperaría una gran cantidad de afirmaciones fallidas).
En primer lugar, os.Exit()
se puede utilizar para salir del programa normalmente sin errores, y no entrar en pánico, así que esa es una distinción clave. Otra es que el pánico en algún lugar puede detectarse e ignorarse o registrarse mediante recover
.
Pero si estamos hablando de un código de salida erróneo, digamos:
Úselo panic
cuando algo salga terriblemente mal, probablemente un error del programador que debería haberse detectado antes de pasar a producción. Por eso imprime la pila.
Usa os.Exit(errorCode)
o algo así si quieres:
controlar el código de salida del programa con fines de secuencia de comandos.
desea una salida ordenada en caso de un error esperado (por ejemplo, error de entrada del usuario).
Así que básicamente el pánico es para ti, un código de salida incorrecto es para tu usuario.
Las diferencias clave son:
os.Exit
omite la ejecución de la función diferida.os.Exit
, puede especificar el código de salida.panic
está terminando mientras os.Exit
que no. (Parece que otras respuestas no mencionan esto).Si necesita ejecutar la función diferida, no tiene más remedio que panic
. (Por otro lado, si desea omitir la ejecución de la función diferida, utilice os.Exit
.)
Si una función no nula se define de tal manera:
return
opanic
Entonces no puede reemplazar panic
con, de lo os.Exit
contrario, el compilador se negará a compilar el programa, diciendo "falta el retorno al final de la función". (Go es muy tonto aquí, incluso log.Panic
no termina una función).
En otras condiciones:
panic
cuando ocurra algo realmente cableado, por ejemplo, error de lógica de programación.os.Exit
cuando desee una salida inmediata, con un código de salida especificado.
panic
se usa para salir en caso de error, simplemente por el hecho de que es fácil de entender y elimina la importación de otros paquetes. ¡Esto no significa que sea una buena práctica o idiomática! . Es solo un dispositivo que ahorra espacio, por ejemplo, el código. Reserva IRLpanic
para situaciones muy especiales.panic
es un incorporado. Se recomienda (según las circunstancias) usar algo comoos.Exit
,log.Fatal
etc., que devolverá un código de error al sistema operativo (siempre recomendado si es posible). Todo esto implica la importación de un paquete y, por lo tanto, el código de ejemplo "desordenado". El código de ejemplo siempre debe tomarse solo para demostrar una solución a un problema específico. Puede haber otros problemas con el código, que lo hacen más complejo si se demuestra correctamente y, por lo tanto, restan valor a la explicación de la respuesta dada. YMMV.