一、一個函數中多個defer的執行順序
defer 的作用就是把defer關鍵字之后的函數執行壓入一個棧中延遲執行,多個defer
的執行順序是后進先出LIFO,也就是先執行最后一個defer,最后執行第一個defer
eg:
輸出:
二、defer、return、返回值的執行返回值順序
在此之前,先理解一下return返回值的運行機制:return並非原子操作,共分為賦值、返回值兩步操作。
defer、return、返回值三者的執行是:return最先執行,先將結果寫入返回值中(即賦值);接着defer開始執行一些收尾工作;最后函數攜帶當前返回值退出(即返回值)。
1、不帶命名返回值
如果函數的返回值是無名的(不帶命名返回值),則go語言會在執行return的時候會執行一個類似創建一個臨時變量作為保存return值的動作。
eg:
輸出:
解釋:
如上例子,實際上一共執行了3步操作,
1)賦值,因為返回值沒有命名,所以return 默認指定了一個返回值(假設為s),首先將i賦值給s,i初始值是0,所以s也是0
2)后續的defer操作因為是針對i,進行的,所以不會影響s, 此后因為s不會更新,所以s不會變還是0
3)返回值,return s,也就是return 0
相當於:
var i int
s := i
return s
2、有名返回值
有名返回值的函數,由於返回值在函數定義的時候已經將該變量進行定義,在執行return的時候會先執行返回值保存操作,而后續的defer函數會改變這個返回值(雖然defer是在return之后執行的,但是由於使用的函數定義的變量,所以執行defer操作后對該變量的修改會影響到return的值。
eg:
輸出:
解釋:
s 就相當於命名的變量i,因為所有的操作都是基於命名變量i(s),返回值也是i,所以每一次defer操作,都會更新返回值,執行完defer后,會返回最終i的值。
三、defer詳解
https://www.cnblogs.com/l199616j/p/15500696.html