go defer理解

golang的defer是怎么工作的磷蛹?defer在golang里是一個(gè)很基礎(chǔ)的關(guān)鍵字,在函數(shù)內(nèi)部使用defer聲明的語句會(huì)在函數(shù)退出時(shí)執(zhí)行溪烤,那具體是怎么工作的那味咳?這里通過一個(gè)例子給大家講解下庇勃。

首先大家需要理解函數(shù)的執(zhí)行過程。我理解代碼在編譯的時(shí)候就已經(jīng)確定了函數(shù)的執(zhí)行過程槽驶,當(dāng)解析到defer關(guān)鍵字時(shí)责嚷,將defer函數(shù)放在defer堆棧的棧底,這樣如果一個(gè)函數(shù)有多個(gè)defer聲明時(shí)掂铐,就遵循先進(jìn)后出的原則罕拂,倒敘輸出,這也就是下面這個(gè)例子的輸出結(jié)果:

func defer_call() {?

????deferfunc() {

????????fmt.Println("打印前")

}()

defer func() {

????????fmt.Println("打印中")

}()?

defer func() {?

?????????fmt.Println("打印后")

}()

panic("觸發(fā)異常")

}

輸出結(jié)果:

打印后

打印中

打印前

上面的例子相對(duì)比較好理解全陨,和我們的堆棧以一摸一樣爆班。下面再和大家一起解析一個(gè)經(jīng)典的例子,如下:

func calc(index string,a,b int) int {?

????ret := a+b

? ?fmt.Println(index,a,b,ret)

????return ret

}

func main() {

????a:=1

????b:=2

????defer calc("1",a,calc("10",a,b))

?????a=0

?????defer calc("2",a,calc("20",a,b))

????b=1

}

大家可以有興趣的跑一下這個(gè)demo辱姨∈疗校看看輸出結(jié)果。輸出如下:

10 1 2 3

20 0 2 2

2 0 2 2?

1 1 3 4

下面帶領(lǐng)大家一起解析下炮叶。

第一步 解析上面的main函數(shù)

a =1 b =2 碗旅,然后遇到defer關(guān)鍵字,將defer聲明的calc壓入棧底镜悉,此時(shí)獲取變量的值分別為calc(1,1,calc("10",a,b)),發(fā)現(xiàn)第三個(gè)變量是一個(gè)函數(shù)祟辟,因此繼續(xù)將該函數(shù)解析運(yùn)算。

即第一次輸出calc("10",1,2)==>> 10,1,2,3, 結(jié)果ret=3.將上一步的calc(1,1,calc("10",a,b))替換為calc(1,1,3)侣肄,然后壓入到棧底旧困。

第二步 程序繼續(xù)解析,a=0稼锅,然后遇到第二個(gè)defer關(guān)鍵字吼具,解析defer后的函數(shù)calc("2",a,calc("20",a,b)),和第一步的情況一樣矩距,先進(jìn)行數(shù)值替換上式替換為calc("2",0,calc("20",0,b))拗盒,然后再將第三個(gè)參數(shù)函數(shù)calc("20",0,b)展開為calc("20",0,2),==>>20锥债,0陡蝇,2,2哮肚,結(jié)果ret=2.將上一步的calc("2",a,calc("20",a,b))替換為calc("2",0,2),然后壓入到棧底登夫。

經(jīng)過上面兩步驟,已經(jīng)輸出了10允趟,1恼策,2,3和20潮剪,0涣楷,2分唾,2。第一個(gè)例子里已經(jīng)說了 defer是按照先入后出的順序執(zhí)行总棵,那程序先執(zhí)行calc("2",0,2)==》2鳍寂,0,2情龄,2.然后再執(zhí)行calc(1,1,3)==>1,1,3,4.

支持整個(gè)程序輸出完成。

下面繼續(xù)說下defer與return的關(guān)系捍壤,通過下面一個(gè)經(jīng)典的例子骤视,大家請(qǐng)看下:

func DeferFunc1(i int) (t int) {

????t = i

????defer func() {

????????t +=3

????}()

????return t

}

func DeferFunc2(i int) int {

????t := i

? ? defer func() {

????????t +=3

????}()

????return t

}

func DeferFunc3(i int) (t int) {

? defer func() {

????????t += i

????}()

????return 2

}

package main?

func main() {

????println(DeferFunc1(1))

????println(DeferFunc2(1))

????println(DeferFunc3(1))

}

上面這個(gè)例子輸出信息是什么那?如果大家能夠打出來4 1 3就可以跳過下面的信息了鹃觉,接下來給大家詳解下专酗。

先說下defer與return的執(zhí)行順序,defer的執(zhí)行順序是在return之后盗扇,也就是說return操作執(zhí)行完之后祷肯,再執(zhí)行defer函數(shù),然后函數(shù)執(zhí)行結(jié)束疗隶。

先說下defer與return的執(zhí)行順序佑笋,defer的執(zhí)行順序是在return之后,也就是說return操作執(zhí)行完之后斑鼻,再執(zhí)行defer函數(shù)蒋纬,然后函數(shù)執(zhí)行結(jié)束。

先說下defer與return的執(zhí)行順序坚弱,defer的執(zhí)行順序是在return之后蜀备,也就是說return操作執(zhí)行完之后,再執(zhí)行defer函數(shù)荒叶,然后函數(shù)執(zhí)行結(jié)束碾阁。

重要的事情說3遍,本著上面的原則些楣,下面的

解析DeferFunc1

看下函數(shù)返回值脂凶,聲明了t變量,說明t變量的作用域?yàn)檎麄€(gè)函數(shù)體

1戈毒、將t賦值i艰猬,也就是1

2、執(zhí)行return t埋市,此時(shí)t=t=1

3冠桃、執(zhí)行defer,t+=3道宅,這樣t=4

4食听、然后函數(shù)結(jié)束胸蛛,經(jīng)過第三步的操作 t已經(jīng)變成了4,所以函數(shù)結(jié)束后樱报,t變量為4

解析DeferFunc2

變量t的作用域?yàn)楹瘮?shù)內(nèi)

1葬项、將t賦值i,也就是1

2迹蛤、執(zhí)行return t民珍,此時(shí)t=1

3、執(zhí)行defer盗飒,t+=3嚷量,這樣t=4

4、然后函數(shù)結(jié)束逆趣,因?yàn)樽兞縯的作用域?yàn)楹瘮?shù)內(nèi)蝶溶,所以函數(shù)結(jié)束后,經(jīng)過第2步宣渗,將return值賦為1抖所,第三步的4并不會(huì)返回。說到這里可能比較難懂痕囱,下面將DeferFunc2修改一下田轧,大家就會(huì)恍然大悟

func DeferFunc2(i int) (result int) {

????t := i

defer func() {

????????t +=3

????}()

return t

}

之前返回值的name給隱藏了,我顯示的定義一個(gè)result咐蝇。然后我們?cè)僖徊讲降慕馕鱿?/p>

1涯鲁、將t賦值i,也就是1

2有序、執(zhí)行return t抹腿,此時(shí)result = t => result=1

3、執(zhí)行defer旭寿,t+=3警绩,這樣t=4

大家再看看函數(shù)執(zhí)行完之后,返回值是多少盅称,這樣大家很容易就知道應(yīng)該是1了吧肩祥?還不懂的同學(xué)從頭再讀一遍吧 ??

解析DeferFunc3

1、執(zhí)行return 2缩膝,return t = 2

2混狠、執(zhí)行defer,t+=1=》t = 3

函數(shù)執(zhí)行結(jié)束疾层,t=3将饺。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子予弧,更是在濱河造成了極大的恐慌刮吧,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,122評(píng)論 6 505
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件掖蛤,死亡現(xiàn)場離奇詭異杀捻,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)蚓庭,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,070評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門致讥,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人彪置,你說我怎么就攤上這事拄踪。” “怎么了拳魁?”我有些...
    開封第一講書人閱讀 164,491評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長撮弧。 經(jīng)常有香客問我潘懊,道長,這世上最難降的妖魔是什么贿衍? 我笑而不...
    開封第一講書人閱讀 58,636評(píng)論 1 293
  • 正文 為了忘掉前任授舟,我火速辦了婚禮,結(jié)果婚禮上贸辈,老公的妹妹穿的比我還像新娘释树。我一直安慰自己,他們只是感情好擎淤,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,676評(píng)論 6 392
  • 文/花漫 我一把揭開白布奢啥。 她就那樣靜靜地躺著,像睡著了一般嘴拢。 火紅的嫁衣襯著肌膚如雪桩盲。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,541評(píng)論 1 305
  • 那天席吴,我揣著相機(jī)與錄音赌结,去河邊找鬼。 笑死孝冒,一個(gè)胖子當(dāng)著我的面吹牛柬姚,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播庄涡,決...
    沈念sama閱讀 40,292評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼量承,長吁一口氣:“原來是場噩夢(mèng)啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起宴合,我...
    開封第一講書人閱讀 39,211評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤焕梅,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后卦洽,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體贞言,經(jīng)...
    沈念sama閱讀 45,655評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,846評(píng)論 3 336
  • 正文 我和宋清朗相戀三年阀蒂,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了该窗。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,965評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡蚤霞,死狀恐怖酗失,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情昧绣,我是刑警寧澤规肴,帶...
    沈念sama閱讀 35,684評(píng)論 5 347
  • 正文 年R本政府宣布,位于F島的核電站夜畴,受9級(jí)特大地震影響拖刃,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜贪绘,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,295評(píng)論 3 329
  • 文/蒙蒙 一兑牡、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧税灌,春花似錦均函、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,894評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至狸窘,卻和暖如春墩朦,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背翻擒。 一陣腳步聲響...
    開封第一講書人閱讀 33,012評(píng)論 1 269
  • 我被黑心中介騙來泰國打工氓涣, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人陋气。 一個(gè)月前我還...
    沈念sama閱讀 48,126評(píng)論 3 370
  • 正文 我出身青樓劳吠,卻偏偏與公主長得像,于是被迫代替她去往敵國和親巩趁。 傳聞我的和親對(duì)象是個(gè)殘疾皇子痒玩,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,914評(píng)論 2 355