Quando usare os.Exit () e panic ()?


92

Qualcuno potrebbe spiegare le principali differenze tra os.Exit()e panic()e come vengono utilizzati nella pratica in Go?


11
Solo un commento che si spera possa aiutare in futuro a leggere il codice Go: in molti esempi di codice, panicviene utilizzato per uscire in caso di errore, semplicemente perché è facile da capire, ed elimina l'importazione di altri pacchetti. Questo non significa che sia una pratica buona o idiomatica! . È solo un dispositivo salvaspazio per il codice di esempio. Riserva IRL panicper situazioni molto speciali.
Intermernet

1
Hm..good) specialmente l'abbreviazione "IRL" - è nuova per me :) Potreste spiegare come il panico elimina l'importazione di pacchetti?
Timur Fayzrakhmanov

4
panicè un builtin. Si consiglia (a seconda delle circostanze) di utilizzare qualcosa di simile os.Exit, log.Fatalecc., Che restituirà un codice di errore al sistema operativo (sempre consigliato se possibile). Tutto ciò comporta l'importazione di un pacchetto, e quindi il codice di esempio "ingombrante". Il codice di esempio dovrebbe sempre essere utilizzato solo per dimostrare una soluzione a un problema specifico. Potrebbero esserci altri problemi con il codice, che rendono il codice più complesso se adeguatamente dimostrato, e quindi sminuiscono la spiegazione della risposta data. YMMV.
Intermernet

1
Ok, capito!) Grazie
mille

2
NP, felice di aiutarti e di aumentare il tuo lessico acronimico :-)
Intermernet

Risposte:


84

Prima di tutto, ogni volta che hai una domanda "come viene utilizzato nella pratica", un buon modo per iniziare è cercare il codice sorgente Go (o qualsiasi base di codice Go abbastanza grande, in realtà) e la documentazione del pacchetto per le risposte.

Ora, os.Exite panicsono abbastanza diversi. panicviene utilizzato quando il programma, o una sua parte, ha raggiunto uno stato irreversibile.

Quando panicviene chiamato, incluso implicitamente per errori di runtime come l'indicizzazione di una sezione fuori dai limiti o il fallimento di un'asserzione di tipo, interrompe immediatamente l'esecuzione della funzione corrente e inizia a srotolare lo stack della goroutine, eseguendo eventuali funzioni differite lungo il percorso. Se quello svolgimento raggiunge la cima dello stack della goroutine, il programma muore.

os.Exitviene utilizzato quando è necessario interrompere immediatamente il programma , senza possibilità di ripristino o eseguire un'istruzione di pulizia differita, e restituisce anche un codice di errore (che altri programmi possono utilizzare per segnalare l'accaduto). Questo è utile nei test, quando sai già che dopo che questo test fallisce, anche l'altro fallirà, quindi potresti anche uscire ora. Può essere utilizzato anche quando il programma ha fatto tutto ciò che doveva fare e ora deve solo uscire, cioè dopo aver stampato un messaggio di aiuto.

Il più delle volte non lo utilizzerai panic(dovresti restituire un errorinvece), e non ne hai quasi mai bisogno os.Exital di fuori di alcuni casi nei test e per la terminazione rapida del programma.


9
"Questo è utile nei test, quando sai già che dopo che questo test fallisce, anche l'altro fallirà ..." Questo odora di un test anti-pattern di test dipendenti. In una suite di test ben scritta, ogni test è indipendente; il risultato di un dato test non dovrebbe mai determinare il risultato di un altro test.
Gotgenes

1
@gotgenes Non necessariamente. Se ho un test che una certa funzione restituisce una struttura non nulla e quel test fallisce, allora posso aspettarmi che anche tutti i test che esaminano i valori della struttura falliranno. È il codice che dipende, non i test. (Detto questo, non lo userei exitin quel caso, mi aspetterei solo una grande pila di affermazioni fallite.)
David Moles

83

Prima di tutto, os.Exit()può essere utilizzato per uscire dal programma normalmente senza errori e non preoccuparti, quindi questa è una distinzione chiave. Un altro è che il panico da qualche parte può essere catturato e ignorato o registrato utilizzando recover.

Ma se stiamo parlando di un codice di uscita errato, diciamo:

Da utilizzare panicquando qualcosa va storto, probabilmente un errore del programmatore che avrebbe dovuto essere rilevato prima di andare in produzione. Questo è il motivo per cui stampa la pila.

Usa os.Exit(errorCode)o qualcosa del genere se vuoi:

  1. controllare il codice di uscita del programma per scopi di scripting.

  2. desidera un'uscita ordinata su un errore atteso (ad esempio errore di input dell'utente).

Quindi fondamentalmente il panico è per te, un cattivo codice di uscita è per il tuo utente.


Grazie molto utile!)
Timur Fayzrakhmanov

14
"Quindi fondamentalmente il panico è per te, un cattivo codice di uscita è per il tuo utente." <-
Suggerimento

1
Potremmo dire che panic () è in qualche modo correlato alla solita chiamata assert () in C normale? Beh ... so che rimuovo sempre la chiamata di asserzione prima di passare alla produzione, le abilito solo quando provo una nuova funzionalità. Quello che sto dicendo è che la maggior parte delle volte uso assert () per verificare invarianti che immagino debbano essere vere nel mio codice. Vedi lo stesso utilizzo di panic ()? :-)
yves Baumes

7

Le differenze principali sono:

  1. os.Exit salta l'esecuzione della funzione differita.
  2. Con os.Exitè possibile specificare il codice di uscita.
  3. panicsta terminando mentre os.Exitnon lo è. (Sembra che altre risposte non lo menzionino.)

Se devi eseguire la funzione differita, non hai altra scelta che panic. (D'altra parte, se vuoi saltare l'esecuzione della funzione differita, usa os.Exit.)

Se una funzione non nulla è definita in questo modo:

  1. la funzione contiene molti rami
  2. tutti i rami vengono terminati con returnopanic

Quindi non puoi sostituire paniccon os.Exitaltrimenti il ​​compilatore rifiuterà di compilare il programma, dicendo "mancante ritorno alla fine della funzione". (Go è molto stupido qui, anche log.Panicse non termina una funzione.)

In altre condizioni:

  1. Da utilizzare panicquando accade qualcosa di veramente cablato, ad es. Errore di logica di programmazione.
  2. Utilizzare os.Exitquando si desidera un'uscita immediata, con il codice di uscita specificato.
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.