遞延函數的執行不僅被延遲,推遲到此刻周圍的函數返回時,它也甚至被處決如果封閉函數突然終止,例如恐慌。 Spec: Defer statements:
A「推遲」語句調用它的執行被推遲到此刻周圍的函數返回的功能,要麼是因爲周圍的功能執行的return statement,達到其function body,或者是因爲相應的goroutine是結束。
當你創建一個值或提供手段妥善關閉/處理它的資源,你應該總是使用一個defer
語句,以確保它是否被釋放,即使你的其他代碼恐慌,以防止泄漏內存或其他系統資源。
這是真的,如果你在一個循環中分配資源,你不應該簡單地使用defer
,作爲然後釋放資源不會發生早,因爲它可以而且應該(在每次迭代結束),之後只for
聲明(僅在所有迭代之後)。
你應該做的是,如果你有一個分配這些資源的代碼片段,將它包裝在一個函數中 - 無論是匿名還是命名函數 - ,並且在那個函數中你可以使用defer
,資源將被釋放爲一旦不再需要它們,重要的是,即使代碼中存在可能引起恐慌的錯誤。
例子:
for rows.Next() {
func() {
fields, err := db.Query(...)
if err != nil {
// Handle error and return
return
}
defer fields.Close()
// do something with `fields`
}()
}
如果放在一個名爲功能:
func foo(rs *db.Rows) {
fields, err := db.Query(...)
if err != nil {
// Handle error and return
return
}
defer fields.Close()
// do something with `fields`
}
,把它:
for rows.Next() {
foo(rs)
}
不要在一個循環內推遲。 – Volker
[Golang推遲澄清]的相關/可能的重複(https://stackoverflow.com/questions/28893586/golang-defer-clarification/28894103#28894103)。 – icza