defer

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

  1. 獲取須要返回值變量,無論返回值是否聲明,對應的都是一個變量;
  2. 棧的形式處理defer函數;
  3. 函數返回

舉例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的值返回
 */

參考資料博客

  1. https://golang.google.cn/ref/spec#Defer_statements
  2. https://blog.csdn.net/shenlanzifa/article/details/51540049 (博客上有個轉字,沒找到原出處,若是知道出處的朋友請告知我,我替換之。)
相關文章
相關標籤/搜索