2013-03-22 2 views
19

Ich weiß, dass Sie Funktionen mit der Bezeichnung init in jedem Paket definieren können, und diese Funktion wird vor main ausgeführt werden. Ich benutze dies, um meine Protokolldatei und meine DB-Verbindung zu öffnen.In go, gibt es eine Möglichkeit Code bei Beendigung des Programms auszuführen?

Gibt es eine Möglichkeit, Code zu definieren, der ausgeführt wird, wenn das Programm endet, entweder weil es das Ende der main-Funktion erreicht oder weil es unterbrochen wurde? Der einzige Weg, an den ich denken kann, ist, manuell eine defered terminate-Funktion auf jedem von main verwendeten Paket aufzurufen, aber das ist ziemlich ausführlich und fehleranfällig.

+1

Ist [diese Frage im Zusammenhang] (http://stackoverflow.com/questions/8403862/do-Aktionen-am-Ende-der-Ausführung) nützlich? So führe ich am Ende der Ausführung Aktionen aus. –

Antwort

27

Die C atexit-Funktionalität wurde von den Go-Entwicklern in Betracht gezogen und die Idee, sie zu übernehmen, wurde abgelehnt.

Von einem der verwandten thread bei golang-Nüsse:

Russ Cox:

atexit kann single-threaded, kurzlebige Programme, aber ich bin skeptisch machen Sinn, dass sie eine hat Platzieren Sie in einem lang laufenden Multi-Thread-Server. Ich habe viele C++ - Programme gesehen, die beim Beenden hängen bleiben, weil globale Destruktoren ausgeführt werden, die nicht wirklich ausführen müssen, und diese Destruktoren werden aufgeräumt und Speicher freigegeben, die vom Betriebssystem sowieso zurückgewonnen werden würde , wenn nur das Programm zum Exit-Systemaufruf gelangen könnte. Verglichen mit all diesem Schmerz, Flush zu rufen, wenn Sie sind, scheint einer mit einem Puffer völlig in Ordnung und ist sowieso notwendig für die korrekte Ausführung von lang laufenden Programmen.

ignorieren Auch dieses Problem, atexit führt noch mehr Fäden der Kontrolle, und Sie haben Fragen wie Sie alle anderen goroutines vor dem atexit Handler Lauf stoppen zu beantworten? Wenn nicht, wie vermeiden sie Störungen? Wenn ja, was passiert, wenn eine Sperre enthält, die der Handler benötigt? Und weiter und weiter.

Ich bin überhaupt nicht geneigt, Atexit hinzuzufügen.

Ian Lance Taylor:

Der einzige vollständig zuverlässiger Mechanismus ist ein Wrapper-Programm, das das richtige Programm und macht die Bereinigung aufruft, wenn das eigentliche Programm abgeschlossen ist. Das gilt in jeder Sprache, nicht nur Go.

In meiner etwas ungeformten Meinung ist os.AtExit keine gute Idee. Es ist eine unstrukturierte Einrichtung, die dazu führt, dass beim Programm-Exit Dinge in einer unvorhersehbaren Reihenfolge passieren. Es führt zu seltsamen Szenarien wie Programme, die eine lange Zeit dauern, nur um zu beenden, eine Operation, die sehr schnell sein sollte. Es führt auch zu seltsamen Funktionen wie der C-Funktion _exit, , die mehr oder weniger Exit-But-Don't-Run-Atexit-Funktionen bedeutet.

Das heißt, ich denke, eine spezielle Exit-Funktion entsprechend der init Funktion ist eine interessante Idee. Es hätte die Struktur, dass os.AtExit fehlt (Exit-Funktionen werden in umgekehrter Reihenfolge ausgeführt, wenn Init-Funktionen ausgeführt werden).

Aber Exit-Funktionen werden Ihnen nicht helfen, wenn Ihr Programm durch den Kernel getötet wird, oder stürzt ab, weil Sie einige C-Code aufrufen, der eine Segmentierung Verletzung erhält.

+2

Danke, das ist ein sehr interessanter Thread. – Fabien

0

Im Allgemeinen stimme ich mit jnmls Antwort überein. Sollten Sie es trotzdem tun wollen, können Sie defer in der main() Funktion verwenden, wie folgt: http://play.golang.org/p/aUdFXHtFOM.

+9

Das Verschieben von Funktionen von 'main' funktioniert nur, wenn das Programm mit' main' beendet wird, nicht mit 'os.Exit', im Gegensatz zum ursprünglichen 'atexit', das auch beim Aufruf von' exit' funktioniert. – guelfey

+3

Es funktioniert auch nicht, wenn das Programm mit einer nicht wiederhergestellten "Panik" beendet wird. – peterSO

+4

@peterSO Sie könnten jedoch in der Deferred-Funktion wiederherstellen, also ist das kein wirkliches Argument gegen 'defer' in' main'. – nemo

Verwandte Themen