golang中的defer
A defer statement is often used with paired operations like open and close, connect and disconnect, or lock and unlock to ensure that resources are released in all cases, no matter how complex the control flow. The right place for a defer statement that releases a resource is immediately after the resource has been successfully acquired.
在golang當中,defer程式碼塊會在函式呼叫連結串列中增加一個函式呼叫。這個函式呼叫不是普通的函式呼叫,而是會在函式正常返回,也就是return之後新增一個函式呼叫。因此,defer通常用來釋放函式內部變數。
func
ReadWrite() bool {
file.Open(
"file"
)
defer
file.Close()
//file.Close() is added to defer list
// Do your thing
if
failureX {
return
false
// Close() is now done automatically
}
if
failureY {
return
false
// And here too
}
return
true
// And here
}
Deferred functions are executed in LIFO order, so the below code prints: 4 3 2 1 0.
package
main
import
"fmt"
func
main() {
for
i :=
0
; i <
5
; i++ {
defer
fmt.Printf(
"%d "
, i)
}
}
defer、return、返回值三者的執行邏輯應該是:return最先執行,return負責將結果寫入返回值中;接著defer開始執行一些收尾工作;最後函式攜帶當前返回值退出。
注意下面兩個例子
這是無名返回值的情況(上圖)
這是有名返回值的情況(上圖)
a()int 函式的返回值沒有被提前宣告,其值來自於其他變數的賦值,而defer中修改的也是其他變數,而非返回值本身,因此函式退出時返回值並沒有被改變。
b()(i int) 函式的返回值被提前宣告,也就意味著defer中是可以呼叫到真實返回值的,因此defer在return賦值返回值 i 之後,再一次地修改了 i 的值,最終函式退出後的返回值才會是defer修改過的值。