defer在函數結束的時候調用一個函數。函數能夠經過return返回,或者是panic引發的結束。golang
DerferStmt = "defer" Expressionc#
表達式必須是一個函數或者是方法調用;不能夠是括號表達式。內置函數要嚴格按照要求表達式規範(部份內置函數沒法用在表達式)。函數
每次defer語句執行,defer函數中的參數與日常同樣的值傳遞方式,在函數中建立一個新的副本。當函數以return結束時,會當即調用defer的函數,而且以聲明defer的逆序方式調用。若是某個defer函數的表達式值爲nil,則會出現panic,defer也不執行。google
例如,若是當前函數有一個命名返回值,在defer的匿名函數中能夠在函數返回前修改這個返回值。spa
若是defer函數有任何的返回值,在函數完成後都會被忽略。.net
最重要的一點:return不是原子指令。code
return語句觸發的三部操做blog
舉例get
//example 1 func example1() (result int) { defer func() { result++ }() return 0 } //能夠理解爲 func example1s() (result int) { defer func() { result++ }() result=0 return } /** * 這裏return觸發一系列操做 * 1.給返回變量賦值 result=0 * 2.處理defer函數,其中defer函數獲取到返回變量的地址,而且完成自加操做 * 3.將返回變量的值返回 */
//example 2 func example2() (result int) { t:=5 defer func() { t=t+5 }() return t } //能夠理解爲 func example2s() (result int) { t:=5 defer func() { t=t+5 }() result=t return } /** * 這裏return觸發一系列操做 * 1.給返回變量result賦值 result=t * 2.處理defer函數,其中defer函數,讓函數中的變量t=t+5 * 3.將返回變量result的值返回 */
//example 3 func example3() (result int) { defer func(result int) { result=result+5 }(result) return 1 } //能夠理解爲 func example3s() (result int) { defer func(result int) { result=result+5 }(result) result=1 return } /** * 這裏return觸發一系列操做 * 1.給返回變量result賦值 result=1 * 2.處理defer函數,其中defer函數,defer函數中的形參result進入到函數內部後變爲局部變量,而後在加法運算,但 * 形參的變化並不會影響外部的同名參數 * 3.將返回變量result的值返回 */
參考資料博客