Go ---- defer 和 return 執行的先后順序


Go 中 defer 和 return 執行的先后順序

  1. 多個defer的執行順序為“后進先出”;

  2. defer、return、返回值三者的執行邏輯應該是:return最先執行,return負責將結果寫入返回值中;接着defer開始執行一些收尾工作;最后函數攜帶當前返回值退出。

 

如果函數的返回值是無名的(不帶命名返回值),則go語言會在執行return的時候會執行一個類似創建一個臨時變量作為保存return值的動作,而有名返回值的函數,由於返回值在函數定義的時候已經將該變量進行定義,在執行return的時候會先執行返回值保存操作,而后續的defer函數會改變這個返回值(雖然defer是在return之后執行的,但是由於使用的函數定義的變量,所以執行defer操作后對該變量的修改會影響到return的值

eg1:不帶命名返回值的函數

package main

import "fmt"

func main() {
	fmt.Println("return:", test())// defer 和 return之間的順序是先返回值, i=0,后defer
}

func test() int {//這里返回值沒有命名
	var i int
	defer func() {
		i++
		fmt.Println("defer1", i) //作為閉包引用的話,則會在defer函數執行時根據整個上下文確定當前的值。i=2
	}()
	defer func() {
		i++
		fmt.Println("defer2", i) //作為閉包引用的話,則會在defer函數執行時根據整個上下文確定當前的值。i=1
	}()
	return i
} 

test() 先返回 i=0

defer2先於defer1執行

輸出結果為:

defer2 1

defer1 2

return: 0

 

 

eg2:帶命名返回值的函數:

package main

import "fmt"

func main() {
	fmt.Println("return:", test())
}

func test() (i int) { //返回值命名i 
	defer func() {
		i++
		fmt.Println("defer1", i)
	}()
	defer func() {
		i++
		fmt.Println("defer2", i)
	}()
	return i
}
對外部變量的引用作為函數參數(i),則在defer申明時就把值傳遞給defer,

 

 輸出結果為:

defer2 1

defer1 2

return: 2

理解return 返回值的運行機制:

為了弄清上述兩種情況的區別,我們首先要理解return 返回值的運行機制:
return 並非原子操作,分為賦值,和返回值兩步操作
eg1 : 實際上return 執行了兩步操作,因為返回值沒有命名,所以
return 默認指定了一個返回值(假設為s),首先將i賦值給s,后續
的操作因為是針對i,進行的,所以不會影響s, 此后因為s不會更新,所以
return s 不會改變
相當於:
var i int
s := i
return s
eg2 : 同上,s 就相當於 命名的變量i, 因為所有的操作都是基於
命名變量i(s),返回值也是i, 所以每一次defer操作,都會更新
返回值i

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM