最美情侣中文字幕电影,在线麻豆精品传媒,在线网站高清黄,久久黄色视频

歡迎光臨散文網(wǎng) 會(huì)員登陸 & 注冊(cè)

一道 Go 閉包題,面試官說原來自己答錯(cuò)了:面別人也漲知識(shí)

2023-04-11 10:41 作者:清澄秋爽  | 我要投稿

https://mp.weixin.qq.com/s?src=11&timestamp=1681177762&ver=4461&signature=tDrLTglFWX-CV4RvwjPLjy8v*zTZKvFa4pHcHB75Wjkf8Hs3PyTtbYgJojc6ukwrarw9lpTgr5vFfXLJ*7E3dKgGfm*H4esRwOyxM0GRri1fsDeKRyqofnfWhj8R4vc7&new=1

大家好,我是站長(zhǎng) polarisxu。

通常,JS 面試,閉包應(yīng)該是必考的題目。隨著越來越多的語(yǔ)言對(duì)函數(shù)式范式的支持,閉包問題經(jīng)常出現(xiàn)。在 Go 語(yǔ)言中也是如此。

本文從一道題引出 Go 中的閉包。這是 Go 語(yǔ)言愛好者周刊第 90 期的一道題目。以下代碼輸出什么?

這道題目答對(duì)的人蠻多的:60%。不管你是答對(duì)還是答錯(cuò),如果最后再加一行代碼:fmt.Println(a("All")),它輸出什么?想看看你是不是蒙對(duì)了。(提示:你可以輸出 t 的地址,看看是什么情況。)

01 什么是閉包

維基百科對(duì)閉包的定義:

在計(jì)算機(jī)科學(xué)中,閉包(英語(yǔ):Closure),又稱詞法閉包(Lexical Closure)或函數(shù)閉包(function closures),是在支持頭等函數(shù)的編程語(yǔ)言中實(shí)現(xiàn)詞法綁定的一種技術(shù)。閉包在實(shí)現(xiàn)上是一個(gè)結(jié)構(gòu)體,它存儲(chǔ)了一個(gè)函數(shù)(通常是其入口地址)和一個(gè)關(guān)聯(lián)的環(huán)境(相當(dāng)于一個(gè)符號(hào)查找表)。環(huán)境里是若干對(duì)符號(hào)和值的對(duì)應(yīng)關(guān)系,它既要包括約束變量(該函數(shù)內(nèi)部綁定的符號(hào)),也要包括自由變量(在函數(shù)外部定義但在函數(shù)內(nèi)被引用),有些函數(shù)也可能沒有自由變量。閉包跟函數(shù)最大的不同在于,當(dāng)捕捉閉包的時(shí)候,它的自由變量會(huì)在捕捉時(shí)被確定,這樣即便脫離了捕捉時(shí)的上下文,它也能照常運(yùn)行。捕捉時(shí)對(duì)于值的處理可以是值拷貝,也可以是名稱引用,這通常由語(yǔ)言設(shè)計(jì)者決定,也可能由用戶自行指定(如 C++)。

關(guān)于(函數(shù))閉包,有幾個(gè)關(guān)鍵點(diǎn):

  • 函數(shù)是一等公民;

  • 閉包所處環(huán)境,可以引用環(huán)境里的值;

問到什么是閉包時(shí),網(wǎng)上一般這么回答的:

在支持函數(shù)是一等公民的語(yǔ)言中,一個(gè)函數(shù)的返回值是另一個(gè)函數(shù),被返回的函數(shù)可以訪問父函數(shù)內(nèi)的變量,當(dāng)這個(gè)被返回的函數(shù)在外部執(zhí)行時(shí),就產(chǎn)生了閉包。

所以,上面題目中,函數(shù) app 的返回值是另一個(gè)函數(shù),因此產(chǎn)生了閉包。

02 Go 中的閉包

Go 中的函數(shù)是一等公民,之前寫過一篇文章:函數(shù)是一等公民,這到底在說什么?

日常開發(fā)中,閉包是很常見的。舉幾個(gè)例子。

標(biāo)準(zhǔn)庫(kù)

在 net/http 包中的函數(shù) ProxyURL,實(shí)現(xiàn)如下:

它的返回值是另一個(gè)函數(shù),簽名是:

在返回的函數(shù)中,引用了父函數(shù)(ProxyURL)的參數(shù) fixedURL,因此這是閉包。

Web 中間件

在 Web 開發(fā)中,中間件一般都會(huì)使用閉包。比如 Echo 框架中的一個(gè)中間件:

首先,echo.MiddlewareFunc 是一個(gè)函數(shù):

而 echo.HandlerFunc 也是一個(gè)函數(shù):

所以,上面的函數(shù)嵌套了幾層,是典型的閉包。

這是閉包嗎?

在 Go 中不支持函數(shù)嵌套定義,函數(shù)內(nèi)嵌套函數(shù),必須通過匿名函數(shù)的形式。匿名函數(shù)在 Go 中是很常見的,比如開啟一個(gè) goroutine,通常通過匿名函數(shù)。

現(xiàn)在有一個(gè)問題,以下代碼是閉包嗎?

如果按照上面網(wǎng)上一般的回答,這不是閉包,因?yàn)椴]有返回函數(shù)。但按照維基百科的定義,這個(gè)屬于閉包。有沒有其他證據(jù)呢?

在 Go 語(yǔ)言規(guī)范中,關(guān)于函數(shù)字面值(匿名函數(shù))有這么一句話:

Function literals are closures: they may refer to variables defined in a surrounding function. Those variables are then shared between the surrounding function and the function literal, and they survive as long as they are accessible.

也就是說,函數(shù)字面值(匿名函數(shù))是閉包,它們可以引用外層函數(shù)定義的變量。

此外,在官方 FAQ 中有這樣的說明:

What happens with closures running as goroutines?

例子是:

這是 Go 中很常見的代碼(很容易寫錯(cuò)的),F(xiàn)AQ 稱開啟 goroutine 的那個(gè)匿名函數(shù)是一個(gè)閉包。

03 匯編看看實(shí)現(xiàn)

回到開始的題目,我們通過匯編看看,Go 閉包的實(shí)現(xiàn),是不是按照維基百科說的,「閉包在實(shí)現(xiàn)上是一個(gè)結(jié)構(gòu)體,它存儲(chǔ)了一個(gè)函數(shù)(通常是其入口地址)和一個(gè)關(guān)聯(lián)的環(huán)境(相當(dāng)于一個(gè)符號(hào)查找表)」。

看關(guān)鍵代碼:

其中 LEAQ type.noalg.struct { F uintptr; "".t string }(SB), AX 這行表明 Go 對(duì)閉包的實(shí)現(xiàn)和維基百科說的類似。

現(xiàn)在看看下面這種是不是這么實(shí)現(xiàn)的:

看看匯編

發(fā)現(xiàn)并沒有這樣的結(jié)構(gòu)體,可見 Go 對(duì)這種情況做了特殊處理,因?yàn)樗皇侵貜?fù)使用的匿名函數(shù)。

04 總結(jié)

通過以上的講解,對(duì)閉包應(yīng)該有了更清晰的認(rèn)識(shí)。如果面試中再被問到閉包,你可以這么回答:

對(duì)閉包來說,函數(shù)在該語(yǔ)言中得是一等公民。一般來說,一個(gè)函數(shù)返回另外一個(gè)函數(shù),這個(gè)被返回的函數(shù)可以引用外層函數(shù)的局部變量,這形成了一個(gè)閉包。通常,閉包通過一個(gè)結(jié)構(gòu)體來實(shí)現(xiàn),它存儲(chǔ)一個(gè)函數(shù)和一個(gè)關(guān)聯(lián)的上下文環(huán)境。但 Go 語(yǔ)言中,匿名函數(shù)就是一個(gè)閉包,它可以直接引用外部函數(shù)的局部變量,因?yàn)?Go 規(guī)范和 FAQ 都這么說了。

面試官會(huì)不會(huì)被你驚到:原來如此,后一種說法我之前沒有注意過。



往期推薦

  • 為什么 Go 標(biāo)準(zhǔn)庫(kù)中有些函數(shù)只有簽名,沒有函數(shù)體?

  • 函數(shù)是一等公民,這到底在說什么?



一道 Go 閉包題,面試官說原來自己答錯(cuò)了:面別人也漲知識(shí)的評(píng)論 (共 條)

分享到微博請(qǐng)遵守國(guó)家法律
沾化县| 柞水县| 中阳县| 华蓥市| 府谷县| 伊吾县| 普格县| 元阳县| 迁安市| 遵化市| 元氏县| 万安县| 怀仁县| 右玉县| 育儿| 澄城县| 琼结县| 道孚县| 枣阳市| 桓台县| 大新县| 莱西市| 乌拉特中旗| 平和县| 行唐县| 内江市| 南通市| 萨迦县| 喀喇沁旗| 上高县| 宁国市| 宣汉县| 石景山区| 湖北省| 巴里| 平泉县| 浠水县| 阿瓦提县| 玉田县| 嘉鱼县| 阿克陶县|