Golang之Defer

引用

使用

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í)行順序

  1. 先給返回值賦值
  2. 執(zhí)行defer語(yǔ)句
  3. 包裹函數(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.

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容