一文了解defer操作

什么是defer?

defer是go語言提供的一種用于注冊延遲調(diào)用的機制悦污,讓函數(shù)或語句可以在當前函數(shù)執(zhí)行完畢后(包括通過return正常結(jié)束或panic導致的異常結(jié)束)執(zhí)行抗悍。

適用場景:

  • 打開/關(guān)閉連接
  • 加鎖/釋放鎖
  • 打開/關(guān)閉文件等

defer在一些需要回收資源的場景非常有用,可以很方便在函數(shù)結(jié)束前做一些清理工作搏存。

為什么要用defer秫舌?

在編程過程中的妖,經(jīng)常需要打開一些資源,比如數(shù)據(jù)庫足陨、文件嫂粟、鎖等,這些資源都需要用完釋放墨缘,否則會造成內(nèi)存泄漏星虹。

當然在使用過程中零抬,可以在函數(shù)結(jié)束時顯式關(guān)閉資源,但是如果在打開和關(guān)閉資源之間如果發(fā)生了panic會退出函數(shù)宽涌,導致關(guān)閉資源沒有被執(zhí)行平夜。因為這樣一顆語法糖,減少了很多資源泄漏的情況卸亮。

defer底層

官方對defer的解釋:

Each time a “defer” statement executes, the function value and parameters to the call are evaluated as usual and saved anew but the actual function is not invoked. Instead, deferred functions are invoked immediately before the surrounding function returns, in the reverse order they were deferred. If a deferred function value evaluates to nil, execution panics when the function is invoked, not when the “defer” statement is executed.

每次defer語句執(zhí)行時忽妒,會把函數(shù)“壓棧”嫡良,函數(shù)的參數(shù)會被拷貝下來锰扶,當外層函數(shù)退出時献酗,defer函數(shù)按照定義的逆序執(zhí)行寝受,如果defer執(zhí)行的函數(shù)為nil,那么會在最終調(diào)用函數(shù)產(chǎn)生panic罕偎。

這里有一道經(jīng)典題:

func main() {
    a,b := 1,2
    defer cal("1",a,cal("10",a,b))
    a = 0
    defer cal("2",a,cal("20",a,b))
}

func cal(index string, a, b int) int {
    ret := a + b
    fmt.Println(index,a,b,ret)
    return ret
}

// Output:
10 1 2 3
20 0 2 2
2 0 2 2
1 1 3 4

這是遵循先入后出的原則很澄,同時保留當前變量的值。

看看下面這道題:

func f1() (r int) {
    defer func() {
        r++
    }
    return 0
}

func f2() (r int) {
    t := 5
    defer func() {
        t = t + 5
    }
    return t
}

func f3() (r int) {
    defer func(r int) {
        r = r + 5
    }(r)
    return 1
}

// Output:
1
5
1

你能正確答對嗎颜及?

關(guān)鍵點在于理解這條語句:

return xxx

這條語句并不是一個原子命令甩苛,經(jīng)過編譯后,變成3條指令:

1俏站、返回值=xxx
2讯蒲、調(diào)用defer函數(shù)
3、空的return

那么我們來拆解上面3個函數(shù)肄扎。

func f1() (r int) {
    // 1墨林、賦值
    r = 0
    // 2、閉包引用
    defer func() {
        r++
    }
    // 3犯祠、空的return
    return 0
}
// defer是閉包引用旭等,所以返回值被修改,所以f1()返回1

func f2() (r int) {
    t := 5
    // 1衡载、賦值
    r = t
    // 2搔耕、閉包引用,但沒有修改r
    defer func() {
        t = t + 5
    }
    // 3痰娱、空的return
    return t
}
// 沒涉及返回值r的操作弃榨,所以返回5

func f3() (r int) {
    // 1、賦值
    r = 1
    // 2梨睁、r作為參數(shù)傳值惭墓,不會修改返回值的r
    defer func(r int) {
        r = r + 5
    }(r)
    // 3、空的return
    return 
}
// 第二步r是作為函數(shù)參數(shù)使用的而姐,是一份復制腊凶,defer語句中的r和外面的r是兩個變量,里面r的變化不會改變外面r,所以返回1.
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末钧萍,一起剝皮案震驚了整個濱河市褐缠,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌风瘦,老刑警劉巖队魏,帶你破解...
    沈念sama閱讀 211,948評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異万搔,居然都是意外死亡胡桨,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,371評論 3 385
  • 文/潘曉璐 我一進店門瞬雹,熙熙樓的掌柜王于貴愁眉苦臉地迎上來昧谊,“玉大人,你說我怎么就攤上這事酗捌∧匚埽” “怎么了?”我有些...
    開封第一講書人閱讀 157,490評論 0 348
  • 文/不壞的土叔 我叫張陵胖缤,是天一觀的道長尚镰。 經(jīng)常有香客問我,道長哪廓,這世上最難降的妖魔是什么狗唉? 我笑而不...
    開封第一講書人閱讀 56,521評論 1 284
  • 正文 為了忘掉前任,我火速辦了婚禮涡真,結(jié)果婚禮上分俯,老公的妹妹穿的比我還像新娘。我一直安慰自己综膀,他們只是感情好澳迫,可當我...
    茶點故事閱讀 65,627評論 6 386
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著剧劝,像睡著了一般橄登。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上讥此,一...
    開封第一講書人閱讀 49,842評論 1 290
  • 那天拢锹,我揣著相機與錄音,去河邊找鬼萄喳。 笑死卒稳,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的他巨。 我是一名探鬼主播充坑,決...
    沈念sama閱讀 38,997評論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼减江,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了捻爷?” 一聲冷哼從身側(cè)響起辈灼,我...
    開封第一講書人閱讀 37,741評論 0 268
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎也榄,沒想到半個月后巡莹,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,203評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡甜紫,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,534評論 2 327
  • 正文 我和宋清朗相戀三年降宅,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片囚霸。...
    茶點故事閱讀 38,673評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡腰根,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出邮辽,到底是詐尸還是另有隱情唠雕,我是刑警寧澤贸营,帶...
    沈念sama閱讀 34,339評論 4 330
  • 正文 年R本政府宣布吨述,位于F島的核電站,受9級特大地震影響钞脂,放射性物質(zhì)發(fā)生泄漏揣云。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,955評論 3 313
  • 文/蒙蒙 一冰啃、第九天 我趴在偏房一處隱蔽的房頂上張望邓夕。 院中可真熱鬧,春花似錦阎毅、人聲如沸焚刚。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,770評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽矿咕。三九已至,卻和暖如春狼钮,著一層夾襖步出監(jiān)牢的瞬間碳柱,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,000評論 1 266
  • 我被黑心中介騙來泰國打工熬芜, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留莲镣,地道東北人。 一個月前我還...
    沈念sama閱讀 46,394評論 2 360
  • 正文 我出身青樓涎拉,卻偏偏與公主長得像瑞侮,于是被迫代替她去往敵國和親的圆。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 43,562評論 2 349

推薦閱讀更多精彩內(nèi)容