2013-03-22 11 views
19

So che è possibile definire le funzioni chiamate init in qualsiasi pacchetto, e queste funzioni verranno eseguiti prima main. Io uso questo per aprire il mio file di registro e la mia connessione DB.In go, c'è un modo per eseguire il codice alla fine del programma?

C'è un modo per definire il codice che verrà eseguito al termine del programma, o perché raggiunge la fine della funzione main o perché è stato interrotto? L'unico modo che posso pensare è chiamando manualmente una funzione terminate deffered su ogni pacchetto usato da main, ma è abbastanza prolisso e soggetto a errori.

+1

è [questa domanda correlata] (http://stackoverflow.com/questions/8403862/do-actions-on-end-of-execution) utile? Ecco come eseguo le azioni alla fine dell'esecuzione. –

risposta

27

La funzionalità C atexit è stato considerato dagli sviluppatori Go e l'idea di adottare è stata respinta.

Da una delle relative thread a golang-dadi:

Russ Cox:

atexit può avere senso in single-threaded, di breve durata programmi, ma io sono scettico che ha un inserire in un server multi-threaded long-running . Ho visto molti programmi C++ che pendono in uscita perché sono in esecuzione i distruttori globali che in realtà non hanno bisogno di corsa, e quei distruttori stanno pulendo e liberando memoria che sarebbe stato recuperato dal sistema operativo comunque , se solo il programma potrebbe arrivare alla chiamata di sistema di uscita. Rispetto a tutto il dolore, il bisogno di chiamare Flush quando si è uno con un buffer sembra del tutto ragionevole ed è necessario in ogni caso per la corretta esecuzione dei programmi di lunga durata.

Anche ignorando il problema, atexit introduce ancora più thread di controllo, e si deve rispondere a domande come fanno tutti gli altri goroutines fermano prima della gestori atexit periodo? In caso contrario, come evitare di interferire? In tal caso, cosa succede se uno contiene un blocco di cui ha bisogno il gestore? E avanti e avanti.

Io non sono affatto inclini ad aggiungere atexit.

Ian Lance Taylor:

L'unico meccanismo completamente affidabile è un programma involucro che richiama il programma reale e fa la pulizia quando il programma vero completata. Che è vero in qualsiasi lingua, non solo Go.

A mio parere un po 'informe, os.AtExit non è una grande idea. Si tratta di una struttura non strutturato che provoca roba accada all'uscita programma tempo in un ordine imprevedibile. Porta a strani scenari come i programmi che impiegano molto tempo per uscire, un'operazione che dovrebbe essere molto veloce. Porta anche a funzioni bizzarre come la funzione C _exit, che più o meno significa uscite-ma-non-eseguire-atexit-funzioni.

Detto, ritengo una funzione speciale di uscita corrispondente alla init funzione è un'idea interessante. Avrebbe la struttura che os.Mancanza di AtExit (vale a dire, le funzioni di uscita vengono eseguite nell'ordine inverso rispetto a quando vengono eseguite le funzioni di init ).

Ma uscita funzioni non vi aiuterà se il programma viene ucciso dal kernel , o si blocca perché si chiama un codice C che ottiene una segmentazione violazione.

+2

Grazie, questa è una discussione molto interessante. – Fabien

0

In generale, sono d'accordo con la risposta di jnml. Se si desidera comunque continuare a farlo, è possibile utilizzare defer nella funzione main(), ad esempio: http://play.golang.org/p/aUdFXHtFOM.

+9

Il rimando delle funzioni da 'main' funziona solo quando il programma termina terminando' main', non se esce tramite 'os.Exit', in contrasto con l'originale' atexit' che funziona anche quando si chiama 'exit'. – guelfey

+3

Né funziona quando il programma termina con un 'panico' non ripristinato. – peterSO

+4

@peterSO Si potrebbe, tuttavia, recuperare nella funzione posticipata, quindi non è un vero argomento contro 'differire' in' main'. – nemo