Go語言 defer

參考文章:深入理解Go語言

defer用于資源的釋放哑梳,會在函數(shù)返回之前進(jìn)行調(diào)用

defer關(guān)鍵字的實(shí)現(xiàn)跟go關(guān)鍵字很類似丁频,不同的是它調(diào)用的是runtime.deferproc而不是runtime.newproc。
在defer出現(xiàn)的地方期犬,插入了指令call runtime.deferproc敞斋,然后在函數(shù)返回之前的地方丹墨,插入指令call runtime.deferreturn。
普通的函數(shù)返回時(shí)龙巨,匯編代碼類似:

add xx SP
return

如果其中包含了defer語句笼呆,則匯編代碼是:

call runtime.deferreturn,
add xx SP
return

goroutine的控制結(jié)構(gòu)中旨别,有一張表記錄defer诗赌,調(diào)用runtime.deferproc時(shí)會將需要defer的表達(dá)式記錄在表中,而在調(diào)用runtime.deferreturn的時(shí)候秸弛,則會依次從defer表中出棧并執(zhí)行铭若。

實(shí)例一:先按照普通函數(shù)執(zhí)行洪碳,然后再按照defer 的先進(jìn)后出逆向執(zhí)行

func main() {
   fmt.Println("hello world 123")
   defer goodBye()
   defer goodNight()
   goodEating()
   fmt.Println("hello world")
}

func goodNight()  {
   fmt.Println("goodnight")
}
func goodBye()  {
   fmt.Println("goodbye")
}
func goodEating()  {
   fmt.Println("goodeating")
}
---------output-----------
hello world 123
goodeating
hello world
goodnight
goodbye

實(shí)例二:若在中間添加一個(gè) return,那么在return之上的叼屠,先按照普通函數(shù)執(zhí)行瞳腌,然后按照defer 的先進(jìn)后出逆向執(zhí)行,在return之下的不執(zhí)行

func main() {
   fmt.Println("hello world 123")
   defer goodBye()
   defer goodNight()
   goodEating()
   return
   fmt.Println("hello world")
}

func goodNight()  {
   fmt.Println("goodnight")
}
func goodBye()  {
   fmt.Println("goodbye")
}
func goodEating()  {
   fmt.Println("goodeating")
}
------output-------
hello world 123
goodeating
goodnight
goodbye

實(shí)例三:返回值操作

func f() (result int) {
    defer func() {
        result++
    }()
    return 0
}

由于 return xxx這一條語句并不是一條原子指令!
所以 return xxx 分為 三步操作 :返回值 = xxx 镜雨,調(diào)用defer函數(shù)嫂侍,空的return,上面代碼可以看作下面的代碼

func f() (result int) {
     result = 0  //return語句不是一條原子調(diào)用荚坞,return xxx其實(shí)是賦值+ret指令
     func() { //defer被插入到return之前執(zhí)行挑宠,也就是賦返回值和ret指令之間
         result++
     }()
     return
}

實(shí)例四:帶參數(shù)的賦值返回值操作

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

上述的return返回的是 t,而我們func的返回值是 r颓影,上面代碼可以看作下面的代碼

func f() (r int) {
     t := 5
     r = t //賦值指令
     func() {        //defer被插入到賦值與返回之間執(zhí)行各淀,這個(gè)例子中返回值r沒被修改過
         t = t + 5
     }
     return        //空的return指令
}

實(shí)例五

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

分析:

func f() (r int) {
     r = 1  //給返回值賦值
     func(r int) {        //這里改的r是傳值傳進(jìn)去的r,不會改變要返回的那個(gè)r值
          r = r + 5
     }(r)
     return        //空的return
}

實(shí)例六

func main() {
   i := deferRet(1,1)
   println(i)  // print 152
}

func deferRet(x,y int) (z int){
   defer func () { z += 100 }()
   z = x + y  
   return z + 50 // 執(zhí)行順序 z = z+50 -> (call defer)z = z+100 -> ret
}

分析:

func deferRet(x,y int) (z int){
   z = x + y // z=2
   z = z+50   //給返回值賦值z=52
  defer z += 100 //z = 150
  return   
}

本質(zhì)原因是return xxx語句并不是一條原子指令诡挂,defer被插入到了賦值 與 ret之間碎浇,因此可能有機(jī)會改變最終的返回值。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末璃俗,一起剝皮案震驚了整個(gè)濱河市奴璃,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌城豁,老刑警劉巖溺健,帶你破解...
    沈念sama閱讀 217,542評論 6 504
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異钮蛛,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)剖膳,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,822評論 3 394
  • 文/潘曉璐 我一進(jìn)店門魏颓,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人吱晒,你說我怎么就攤上這事甸饱。” “怎么了仑濒?”我有些...
    開封第一講書人閱讀 163,912評論 0 354
  • 文/不壞的土叔 我叫張陵叹话,是天一觀的道長。 經(jīng)常有香客問我墩瞳,道長驼壶,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,449評論 1 293
  • 正文 為了忘掉前任喉酌,我火速辦了婚禮热凹,結(jié)果婚禮上泵喘,老公的妹妹穿的比我還像新娘。我一直安慰自己般妙,他們只是感情好纪铺,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,500評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著碟渺,像睡著了一般鲜锚。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上苫拍,一...
    開封第一講書人閱讀 51,370評論 1 302
  • 那天芜繁,我揣著相機(jī)與錄音,去河邊找鬼怯疤。 笑死浆洗,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的集峦。 我是一名探鬼主播伏社,決...
    沈念sama閱讀 40,193評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼塔淤!你這毒婦竟也來了摘昌?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,074評論 0 276
  • 序言:老撾萬榮一對情侶失蹤高蜂,失蹤者是張志新(化名)和其女友劉穎聪黎,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體备恤,經(jīng)...
    沈念sama閱讀 45,505評論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡稿饰,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,722評論 3 335
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了露泊。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片喉镰。...
    茶點(diǎn)故事閱讀 39,841評論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖惭笑,靈堂內(nèi)的尸體忽然破棺而出侣姆,到底是詐尸還是另有隱情,我是刑警寧澤沉噩,帶...
    沈念sama閱讀 35,569評論 5 345
  • 正文 年R本政府宣布捺宗,位于F島的核電站,受9級特大地震影響川蒙,放射性物質(zhì)發(fā)生泄漏蚜厉。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,168評論 3 328
  • 文/蒙蒙 一畜眨、第九天 我趴在偏房一處隱蔽的房頂上張望弯囊。 院中可真熱鬧痰哨,春花似錦、人聲如沸匾嘱。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,783評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽霎烙。三九已至撬讽,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間悬垃,已是汗流浹背游昼。 一陣腳步聲響...
    開封第一講書人閱讀 32,918評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留尝蠕,地道東北人烘豌。 一個(gè)月前我還...
    沈念sama閱讀 47,962評論 2 370
  • 正文 我出身青樓,卻偏偏與公主長得像看彼,于是被迫代替她去往敵國和親廊佩。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,781評論 2 354

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

  • Go語言defer關(guān)鍵字 defer關(guān)鍵字用于延緩函數(shù)的執(zhí)行 只需要在調(diào)用普通函數(shù)或方法前加上關(guān)鍵字defer靖榕,就...
    楠小忎閱讀 3,019評論 1 0
  • 1.ios高性能編程 (1).內(nèi)層 最小的內(nèi)層平均值和峰值(2).耗電量 高效的算法和數(shù)據(jù)結(jié)構(gòu)(3).初始化時(shí)...
    歐辰_OSR閱讀 29,383評論 8 265
  • 一标锄、入駐前,你必須問清的問題1.親茁计,你自己有創(chuàng)業(yè)的經(jīng)歷嗎料皇?你是否有資歷給我的新創(chuàng)公司提建議?現(xiàn)在這世道星压,孵化器比雞...
    EasyAct閱讀 479評論 0 0
  • 最佳藥引:有緣千里來相會娜膘,需往西湖高處尋 01 除去感覺外舷手,面試是一場在“...
    紫竹閱讀 2,842評論 4 21
  • 夜班甘苦人不知 忙里忙外人累死 為了放松緊神經(jīng) 忙里偷閑吟首詩 夜班甘苦人不知 傷眼傷肝誤眠時(shí) 苦點(diǎn)小錢拿命拼 身...
    秋AldrichB果閱讀 219評論 0 9