29

init任意のパッケージで呼び出される関数を定義できることを知っています。これらの関数は の前に実行されmainます。これを使用して、ログ ファイルと DB 接続を開きます。

main関数の最後に到達したか、中断されたために、プログラムが終了したときに実行されるコードを定義する方法はありますか? 私が考えることができる唯一の方法は、メインで使用される各パッケージで遅延関数を手動で呼び出すことですterminateが、それは非常に冗長でエラーが発生しやすくなります。

4

3 に答える 3

37

Catexit機能は Go 開発者によって検討され、それを採用するという考えは拒否されました。

golang-nutsの関連スレッドの 1 つから:

ラス・コックス

Atexit は、シングルスレッドの短期間のプログラムでは意味があるかもしれませんが、長時間実行されるマルチスレッド サーバーで使用できるかどうかは懐疑的です。実際には実行する必要のないグローバルなデストラクタを実行しているため、終了時にハングする多くの C++ プログラムを見てきました。これらのデストラクタは、オペレーティング システムによって再利用されるメモリをクリーンアップして解放しています。 exit システム コールに到達できます。そのすべての苦痛と比較して、バッファを使用しているときに Flush を呼び出す必要があることは完全に合理的であり、長時間実行されるプログラムを正しく実行するために必要です。

その問題を無視しても、atexit はさらに多くの制御スレッドを導入し、atexit ハンドラーが実行される前に他のすべてのゴルーチンが停止するかなどの質問に答える必要があります。そうでない場合、どのようにして干渉を回避しますか? もしそうなら、ハンドラーが必要とするロックを保持している場合はどうなるでしょうか? そしてどんどん。

Atexit を追加する気はまったくありません。

イアン・ランス・テイラー

完全に信頼できる唯一のメカニズムは、実際のプログラムを呼び出し、実際のプログラムの完了時にクリーンアップを行うラッパー プログラムです。これは Go に限らずどの言語でも同じです。

私のやや不明確な意見では、 os.AtExit は良い考えではありません。これは、プログラムの終了時に予期しない順序で物事を発生させる非構造化機能です。これは、非常に高速であるべき操作である、終了するだけで長い時間がかかるプログラムなどの奇妙なシナリオにつながります。また、C 関数 _exit のような奇妙な関数にもつながります。これは多かれ少なかれ、exit-but-don't-run-atexit-functions を意味します。

そうは言っても、init 関数に対応する特別な exit 関数は興味深いアイデアだと思います。os.AtExit にはない構造を持っています (つまり、init 関数が実行されるときとは逆の順序で exit 関数が実行されます)。

しかし、プログラムがカーネルによって強制終了されたり、セグメンテーション違反を起こす C コードを呼び出すためにクラッシュした場合、終了関数は役に立ちません。

于 2013-03-22T09:36:53.367 に答える
2

これをすべて読んだ後(そしておそらくこれを見た後)、まだatexitが必要な場合は、https ://github.com/tebeka/atexitをご覧ください:)

于 2013-03-22T20:40:53.453 に答える
-2

一般的に、jnmlの答えに同意します。それでもやりたい場合は、次のように関数でdeferを使用できます: http://play.golang.org/p/aUdFXHtFOMmain()

于 2013-03-22T09:59:01.320 に答える