這是一個建立於 的文章,其中的資訊可能已經有所發展或是發生改變。
大家都瞭解C++有建構函式和解構函式,加之每一個棧對象都有其嚴格的作用或,離開則自動調用其解構函式,以此來保證釋放其掌控的資源,如:記憶體,檔案,socket,資料庫連結等, 其它一些語言提供類似的機制,如: init, deinit等, 那麼對於追求大道至簡的golang, 她沒有提供建構函式和解構函式的概念, 但是她也不可避免要處理資源的自動釋放問題, 所以其提供了defer, 如: defer f() 用於延遲調用f(), 當此語句所在函數執行完(return執行完)後,開始以“後進先出”的順序執行defer語句。但是defer不是一定會被執行的,我簡單歸總了一下,怕我以後忘記, 見測試代碼:
package mainimport ( "fmt" //"log" //"os")func main() { fmt.Println("test\n") if true { fmt.Println("add defer") defer fmt.Println("defer run!!") //雖然在if的小block中, 但是defer只會到函數執行完時才執行,而不是在離開if範圍時執行。 } fmt.Println("test end\n") //1. defer不會執行了. //log.Fatal() //os.Exit(1) //2. defer會照常執行。 //log.Panic() //panic(nil) //return //reach the end of the function normally.}
通常我們只把os.Exit用於test case代碼中, 生產代碼中很少用,可能有用它的理由就是程式退出時向作業系統報告狀態代碼,但是會中斷defer的執行,為了使資源被正確釋放
掉, 我們可以採用以下代碼的處理方式, 把商務邏輯代碼單獨封裝在一個函數中, 在退出這個函數時,注意只是在函數執行完return以後,與範圍無關 一切defer皆自動執行完,不用再擔心os.Exit()了,見代碼:
func main() { if err := run(); err != nil { fmt.Fprintf(os.Stderr, "error: %v\n", err) os.Exit(1) //當執行此行時, run()早已執行完退出,其中defer早已執行完;但與os.Exit同一內容相關的代碼中就不要用defer了, 因為會被中斷,不再執行。 }}func run() error { err := something() if err != nil { return err } // etc, 這是程式用defer清理資源的最後一條防線。}
參考連結:
http://stackoverflow.com/questions/18963984/exit-with-error-code-in-go
http://stackoverflow.com/questions/28472922/when-to-use-os-exit-and-panic-golang
注意: 此文章只是我個人筆記, 如有錯漏,請一定指正, 共同學習, 我的郵箱: htyu_0203_39@sina.com