2013-03-22 145 views
19

我知道你可以在任何包中定義叫做init的函數,並且這些函數將在main之前執行。我用它來打開我的日誌文件和我的數據庫連接。在去,有沒有辦法執行代碼終止程序?

有沒有一種方法來定義程序結​​束時要執行的代碼,或者是因爲它到達main函數的結尾或者因爲它被中斷了?我能想到的唯一方法是通過在main使用的每個軟件包上手動調用terminate函數,但這非常冗長而且容易出錯。

+1

是[此相關的問題(http://stackoverflow.com/questions/8403862/do-actions-on-end-of-execution)有用嗎?這就是我在執行結束時執行操作的方式。 –

回答

27

Go開發人員考慮了C atexit功能,並且採納它的想法被拒絕了。

從相關thread之一在golang-堅果:

Russ Cox

atexit對可能使意義單線程的,短命 程序,但我懷疑它有一個放置在一個長時間運行的多線程服務器的 中。 我已經看到了掛在退出,因爲 他們正在運行並不真正需要 運行全局銷燬許多C++程序,而那些析構函數清理和釋放內存 將由操作系統 被回收反正,如果只有程序可以進入退出系統調用。 與所有那些痛苦相比,當你需要調用Flush時,如果你有一個緩衝區,看起來是完全合理的,並且無論如何對於正確執行長期運行的 程序是必需的。

即使忽略這個問題,atexit對引入的控制更加 線程,你必須回答這樣的問題 做所有其他的夠程的atexit處理程序 運行前停下來?如果不是,他們如何避免干擾?如果是這樣,如果 持有處理程序需要的鎖定?並繼續。

我根本不想添加Atexit。

Ian Lance Taylor

唯一完全可靠的機制是一個包裝程序真正的程序完成時調用 真正的程序並執行清理。 在任何語言中都是如此,而不僅僅是Go。

在我這個有點不成文的意見中,os.AtExit不是一個好主意。它是 一個非結構化的設施,導致在程序退出 時間以不可預知的順序發生的東西。它會導致奇怪的場景,例如 程序需要很長時間才能退出,應該是非常快速的操作應該是 。它也會導致奇怪的功能,如C函數_exit, ,它們或多或少意味着退出但不運行atexit函數。

這就是說,我認爲對應於init 函數的特殊退出函數是一個有趣的想法。它將具有 os的結構。AtExit缺少(即,退出功能按照 初始化函數運行的相反順序運行)。

但是,如果你的程序被 內核殺死了,退出函數將不會幫助你,或者因爲你調用了一些C代碼而導致分割 違例,所以崩潰。

+2

謝謝,這是一個非常有趣的主題。 – Fabien

0

總的來說,我同意jnml的回答。如果你仍然想要這樣做,你可以在main()函數中使用defer,如下所示:http://play.golang.org/p/aUdFXHtFOM

+9

從'main'推遲函數只能在程序終止時通過'main'終止,而不是通過'os.Exit'退出,相比之下,原來的'atexit'在調用'exit'時也起作用。 – guelfey

+3

當程序終止時出現無法恢復的「恐慌」時,它也不起作用。 – peterSO

+4

@peterSO然而,你可以在延遲函數中恢復,所以這對於'main'中的'defer'沒有真正的爭論。 – nemo

相關問題