golang中的閉包

go語(yǔ)言中函數(shù)可以作為返回值刺彩,可以作為參數(shù),可以作為右值綁定到變量嗡害,golan把這些返回值畦攘,參數(shù)知押,或變量稱為function value,函數(shù)指令在編譯期間生成罢绽,而function value本質(zhì)上是一個(gè)指針良价,指向一個(gè)runtime.funcval結(jié)構(gòu)體蒿叠,這個(gè)結(jié)構(gòu)體里面只有一個(gè)地址——函數(shù)指令的入口地址痊银。假設(shè)有如下代碼:

func A(i int){
    i++
    fmt.Println(i)
}

func B(){
    f1:= A
    f1(1)
}
func C(){
    f2:=A
    f2(1)
}

f1和f2都指向同一個(gè)函數(shù)A(int)魂务,其指令入口為addr1,編譯階段編譯器會(huì)在只讀數(shù)據(jù)段為他分配一個(gè)funcval結(jié)構(gòu)體fn指向addr1鬓照,而他本身的地址會(huì)在執(zhí)行階段賦給f1和f2豺裆,既然只要通過(guò)addr1就可以執(zhí)行函數(shù)A()臭猜,為什么還要通過(guò)fn這個(gè)結(jié)構(gòu)體中轉(zhuǎn)一下呢押蚤,這是為閉包準(zhǔn)備的揽碘。

什么是閉包(closure),用一句話來(lái)描述就是劫灶,閉包是一個(gè)函數(shù)和與他綁定的外部環(huán)境的集合本昏。閉包在實(shí)現(xiàn)上是一個(gè)結(jié)構(gòu)體涌穆,他存儲(chǔ)了一個(gè)函數(shù)(通常是其入口地址)和一個(gè)關(guān)聯(lián)的環(huán)境(相當(dāng)于一個(gè)符號(hào)查找表)宿稀。環(huán)境中包含該函數(shù)的內(nèi)部綁定符號(hào),及其在外部定義但在函數(shù)中引用的自由變量赫编。函數(shù)和閉包的不同在于擂送,當(dāng)捕獲閉包的時(shí)候嘹吨,他的自由變量會(huì)在捕捉時(shí)被確定蟀拷,這樣即使脫離了捕捉時(shí)的上下文萍聊,他也能照樣運(yùn)行寿桨。例如下面的例子:

func create() func()int{
    c:=2
    return func()int{
        return c
    }
}
func main(){
    f1:=create()
    f2:=create()
    fmt.Println(f1())
    fmt.Println(f2())
}

函數(shù)create() func()int就是一個(gè)閉包亭螟,它有自由變量c,當(dāng)create()函數(shù)執(zhí)行結(jié)束墨微,f1和f2依然能夠正常調(diào)用這個(gè)閉包函數(shù)翘县,獲取捕獲變量c的值炼蹦。因?yàn)殚]包包含捕獲變量掐隐,所以在執(zhí)行階段才創(chuàng)建對(duì)應(yīng)的閉包對(duì)象钞馁,假設(shè)create函數(shù)的指令入口為addr1僧凰,在堆上分配一個(gè)funcval的結(jié)構(gòu)體训措,fn指向閉包函數(shù)入口,同時(shí)其捕獲列表中捕獲一個(gè)變量c怀大,然后這個(gè)結(jié)構(gòu)體的地址add2被賦值給f1化借。再次調(diào)用create函數(shù)蓖康,在分配一個(gè)funcval結(jié)構(gòu)體蒜焊,fn指向閉包函數(shù)入口addr1科贬,在捕獲對(duì)應(yīng)的捕獲變量唆迁,還是只有一個(gè)c唐责,最后將這funcval的起始地址addr2賦值給f2鼠哥。

func create() []func() int {
    function := make([](func() int), 2, 2)
    
    for i := 0;i < 2;i++ {
        function[i] = func() int {
            return i
        }
        i++
    }
    return function
}

func main() {
    funcs := create()
    fmt.Println(funcs[0]()) \\ 2
    fmt.Println(funcs[1]()) \\ 2
}

捕獲變量會(huì)發(fā)生改變時(shí),捕獲列表中保存的是捕獲變量的地址允蚣,對(duì)捕獲變量的修改會(huì)保持一致呆贿。因此做入,funcs[0]()funcs[1]()兩個(gè)函數(shù)獲得的i都是2竟块。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末浪秘,一起剝皮案震驚了整個(gè)濱河市耸携,隨后出現(xiàn)的幾起案子违帆,更是在濱河造成了極大的恐慌,老刑警劉巖的畴,帶你破解...
    沈念sama閱讀 222,104評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異煎娇,居然都是意外死亡缓呛,警方通過(guò)查閱死者的電腦和手機(jī)杭隙,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,816評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門(mén)票髓,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)洽沟,“玉大人裆操,你說(shuō)我怎么就攤上這事。” “怎么了朽缴?”我有些...
    開(kāi)封第一講書(shū)人閱讀 168,697評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)或渤。 經(jīng)常有香客問(wèn)我奕扣,道長(zhǎng)惯豆,這世上最難降的妖魔是什么楷兽? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 59,836評(píng)論 1 298
  • 正文 為了忘掉前任芯杀,我火速辦了婚禮揭厚,結(jié)果婚禮上筛圆,老公的妹妹穿的比我還像新娘。我一直安慰自己漾岳,他們只是感情好尼荆,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,851評(píng)論 6 397
  • 文/花漫 我一把揭開(kāi)白布液样。 她就那樣靜靜地躺著鞭莽,像睡著了一般麸祷。 火紅的嫁衣襯著肌膚如雪阶牍。 梳的紋絲不亂的頭發(fā)上走孽,一...
    開(kāi)封第一講書(shū)人閱讀 52,441評(píng)論 1 310
  • 那天磕瓷,我揣著相機(jī)與錄音困食,去河邊找鬼陷舅。 笑死莱睁,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的创淡。 我是一名探鬼主播琳彩,決...
    沈念sama閱讀 40,992評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼碧浊,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼箱锐!你這毒婦竟也來(lái)了劳较?” 一聲冷哼從身側(cè)響起观蜗,我...
    開(kāi)封第一講書(shū)人閱讀 39,899評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤抖仅,失蹤者是張志新(化名)和其女友劉穎岸售,沒(méi)想到半個(gè)月后厂画,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體袱院,經(jīng)...
    沈念sama閱讀 46,457評(píng)論 1 318
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,529評(píng)論 3 341
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了悔雹。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,664評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖锈锤,靈堂內(nèi)的尸體忽然破棺而出久免,到底是詐尸還是另有隱情,我是刑警寧澤摔握,帶...
    沈念sama閱讀 36,346評(píng)論 5 350
  • 正文 年R本政府宣布,位于F島的核電站伊磺,受9級(jí)特大地震影響屑埋,放射性物質(zhì)發(fā)生泄漏摘能。R本人自食惡果不足惜团搞,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,025評(píng)論 3 334
  • 文/蒙蒙 一逻恐、第九天 我趴在偏房一處隱蔽的房頂上張望复隆。 院中可真熱鬧挽拂,春花似錦、人聲如沸台腥。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,511評(píng)論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至嘶是,卻和暖如春聂喇,著一層夾襖步出監(jiān)牢的瞬間希太,已是汗流浹背酝蜒。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,611評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工亡脑, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留霉咨,地道東北人途戒。 一個(gè)月前我還...
    沈念sama閱讀 49,081評(píng)論 3 377
  • 正文 我出身青樓棺滞,卻偏偏與公主長(zhǎng)得像继准,于是被迫代替她去往敵國(guó)和親移必。 傳聞我的和親對(duì)象是個(gè)殘疾皇子毡鉴,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,675評(píng)論 2 359

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

  • 閉包的實(shí)現(xiàn) 很多編程語(yǔ)言都提供了閉包這一特性,那什么是閉包呢幌甘?形象一點(diǎn)來(lái)描述就是“一個(gè)有狀態(tài)的函數(shù)”锅风。對(duì)于普通的函...
    封幼麟閱讀 789評(píng)論 1 3
  • golang中的defer和閉包對(duì)很多初學(xué)者來(lái)說(shuō),有時(shí)候有很多坑,但是很多介紹的文章有寫(xiě)的亂七八糟.放假了沒(méi)事可干...
    myonlyzzy閱讀 2,204評(píng)論 0 0
  • 閉包是自包含的函數(shù)代碼塊肮帐,可以在代碼中被傳遞和使用训枢。Swift 中的閉包與 C 和 Objective-C 中的代...
    CodingIran閱讀 323評(píng)論 0 0
  • 什么是閉包 維基百科中的解釋:在計(jì)算機(jī)科學(xué)中肮砾,閉包(Closure)仗处,又稱詞法閉包(Lexical Closure...
    帥駝駝閱讀 431評(píng)論 0 3
  • swift進(jìn)階 學(xué)習(xí)大綱[http://www.reibang.com/p/0fc67b373540] 在 sw...
    markhetao閱讀 884評(píng)論 0 3