在golang中,我們使用defer語句來進行一些錯誤處理和收尾工作,它的作用類似java里面finally關鍵字的作用。不過不論是java的finally關鍵字還是c++的Raii類,我們都能清楚地知道它們的作用域和執行的時機,那么golang中defer關鍵字所處理的內容是在什么時候執行的呢?http://studygolang.com/articles/2593這篇文章使我豁然開朗。
首先官方文檔里面說了:“A "defer" statement invokes a function whose execution is deferred to the moment the surrounding function returns, either because the surrounding function executed a return statement, reached the end of its function body, or because the corresponding goroutine is panicking.”意思就是函數返回、函數結束或者對應的goroutine發生panic的時候defer就會執行。
然后需要注意的是因為golang支持多值返回,所以是在返回前把返回值壓到棧中的,而c語言是把返回值存到寄存器中返回。
golang返回時,先把返回值壓棧;然后執行defer函數,如果defer函數中有修改棧中的返回值(不過不應該這樣做),那么返回值會被修改;之后進行跳轉返回。
這樣的話我們就清楚了defer執行的時機了,即使你把defer寫在返回之前很遠的地方,它還是會在函數返回之前執行。
如果一個作用域中有多個defer,那么返回前的執行順序是先執行后調用的defer,在執行早調用的defer。
官方文檔里面有幾個例子可以很好地說明defer的作用時機:
1 lock(l) 2 defer unlock(l) // unlocking happens before surrounding function returns 3 4 // prints 3 2 1 0 before surrounding function returns 5 for i := 0; i <= 3; i++ { 6 defer fmt.Print(i) 7 } 8 9 // f returns 1 10 func f() (result int) { 11 defer func() { 12 result++ 13 }() 14 return 0 15 }
