引用
使用
defer是golang提供的關(guān)鍵字鳖轰,在函數(shù)或者方法執(zhí)行完成,返回之前調(diào)用扶镀。
每次defer都會(huì)將defer函數(shù)壓入棧中蕴侣,調(diào)用函數(shù)或者方法結(jié)束時(shí),從棧中取出執(zhí)行臭觉,所以多個(gè)defer的執(zhí)行順序是先入后出昆雀。
Defer規(guī)則
- 延遲函數(shù)的參數(shù)在defer語(yǔ)句出現(xiàn)時(shí)就已經(jīng)確定下來(lái)了
- 延遲函數(shù)執(zhí)行按后進(jìn)先出順序執(zhí)行,即先出現(xiàn)的defer最后執(zhí)行
- 延遲函數(shù)可能操作主函數(shù)的具名返回值
觸發(fā)時(shí)機(jī)
1.包裹著defer語(yǔ)句的函數(shù)返回時(shí)
2.包裹著defer語(yǔ)句的函數(shù)執(zhí)行到最后時(shí)
3.當(dāng)前goroutine發(fā)生Panic時(shí)
返回值執(zhí)行順序
- 先給返回值賦值
- 執(zhí)行defer語(yǔ)句
- 包裹函數(shù)return返回
因此蝠筑,defer狞膘、return、返回值三者的執(zhí)行順序應(yīng)該是:return最先給返回值賦值什乙;接著defer開(kāi)始執(zhí)行一些收尾工作挽封;最后RET指令攜帶返回值退出函數(shù)。
defer命令的拆解
理解這些坑的關(guān)鍵是這條語(yǔ)句:
return xxx
上面這條語(yǔ)句經(jīng)過(guò)編譯之后臣镣,變成了三條指令:
1. 返回值 = xxx
2. 調(diào)用defer函數(shù)
3. 空的return
1,3步才是Return 語(yǔ)句真正的命令辅愿,第2步是defer定義的語(yǔ)句智亮,這里可能會(huì)操作返回值。
下面我們來(lái)看兩個(gè)例子点待,試著將return語(yǔ)句和defer語(yǔ)句拆解到正確的順序阔蛉。
第一個(gè)例子:
func f() (r int) {
t := 5
defer func() {
t = t + 5
}()
return t
}
拆解后:
func f() (r int) {
t := 5
// 1. 賦值指令
r = t
// 2. defer被插入到賦值與返回之間執(zhí)行,這個(gè)例子中返回值r沒(méi)被修改過(guò)
func() {
t = t + 5
}
// 3. 空的return指令
return
}
這里第二步?jīng)]有操作返回值r, 因此癞埠,main函數(shù)中調(diào)用f()得到5.
第二個(gè)例子:
func f() (r int) {
defer func(r int) {
r = r + 5
}(r)
return 1
}
拆解后:
func f() (r int) {
// 1. 賦值
r = 1
// 2. 這里改的r是之前傳值傳進(jìn)去的r状原,不會(huì)改變要返回的那個(gè)r值
func(r int) {
r = r + 5
}(r)
// 3. 空的return
return
}
因此,main函數(shù)中調(diào)用f()得到1.