Go?defer?去掉閉包函數(shù)及用法分析
引言
在 Go 語(yǔ)言里,defer 關(guān)鍵字是大家很愛用的。因?yàn)樗兄?defer+recover+panic 的組合拳打法,還有種各種 defer close 等常用場(chǎng)景。
defer 常見用法
在語(yǔ)法上,Go defer 的代碼示例如下:
package main import "fmt" func main() { defer fmt.Println("煎魚你好!") fmt.Println("放學(xué)別走") }
輸出結(jié)果:
放學(xué)別走
煎魚你好!
那 defer 在 Go 里的常見用法有哪些呢?首先是上文用到的,直接 defer + 函數(shù):
defer f()
其次是 defer+閉包的方式:
defer func() { result := f() // do something with result }()
其他還有在面試題上常被考究的傳參變形:
func f1() int { i := 1 defer func() { i++ }() ... } func f2() int { i := 1 defer func(i int) { i++ }(i) .... }
這些代碼看起來,我們總是在對(duì) defer 做閉包的各種聲明和使用。defer 會(huì)不會(huì)就是和閉包天生一對(duì)?
新提案:defer 代碼塊
最近大家也在討論一個(gè)與之相關(guān)的 Go 提案《proposal: Go 2: deferred code blocks》,由 @Damien Lloyd 提出,想看看有沒有機(jī)會(huì)把 defer 的新語(yǔ)法落地。
原作者在使用 defer 時(shí)也是經(jīng)常:
defer f()
但這樣就無(wú)法獲得返回值。最終要變成:
defer func() { result := f() // do something with result }()
基于上述類似的原因,想引入如下具有 defer 作用的代碼塊語(yǔ)法:
defer { // 在封閉函數(shù)的末尾執(zhí)行此操作 }
在使用了 defer 關(guān)鍵字的函數(shù)最后執(zhí)行這整個(gè)代碼塊 {...}
。代碼塊中的每一行將按順序運(yùn)行。
作者給出的代碼示例:
func fn() { f, err := os.Create("eddycjy.txt") if err != nil { panic(err) } defer { err := f.Close() if err != nil { panic(err) } } }
在 fn 函數(shù),聲明了 defer {...}
,代碼塊內(nèi)是對(duì) f.Close 的兜底判斷和異常拋出。在函數(shù)結(jié)束后執(zhí)行這整個(gè)代碼塊。
反對(duì)的聲音
當(dāng)然,這看著似乎是比較美好的??雌饋碓岚缸髡咧皇呛?jiǎn)化了 defer 是的閉包使用,調(diào)整了作用域的范圍。
但在社區(qū)內(nèi)其實(shí)遭受比較多的反對(duì)聲音。包含但不限于:
1、收益比不高:這個(gè)提案只是避免了 func()
和 ()
等閉包聲明,但是卻要增加新的 defer 語(yǔ)法(語(yǔ)言語(yǔ)法更改會(huì)帶來高昂成本),這個(gè)變更的 ROI 不高。
2、破壞兼容性:原 defer 關(guān)鍵字調(diào)用總是會(huì)跟著函數(shù)的詞法調(diào)用,有良好的一致性。如果進(jìn)行修改,會(huì)產(chǎn)生新的隱晦,破壞一致性。也會(huì)對(duì)現(xiàn)有的許多工具(例如:靜態(tài)分析工具)產(chǎn)生影響,全要改。
3、作用域問題:原本 defer func{}()
的代碼塊結(jié)構(gòu)下,你的代碼作用域都限于閉包函數(shù)下。而使用新的 defer {}
的結(jié)構(gòu),該返回和操作,是否應(yīng)該會(huì)影響到外部函數(shù)的結(jié)果?(這是最有爭(zhēng)議的一點(diǎn),作者也比較前言不搭后語(yǔ),沒明確指明語(yǔ)法意思)
總結(jié)
一開始乍一眼一看,感覺只是把 defer 關(guān)鍵字語(yǔ)句簡(jiǎn)化一下,好像特別好,省了幾個(gè)單詞。就像 if err != nil
也會(huì)有提要用 Rust 的 ?
等用法來替代的。
經(jīng)過社區(qū)網(wǎng)友們指出后,發(fā)現(xiàn)這里貓膩不少。一門已經(jīng)有 10+ 年的編程語(yǔ)言,還有 Go1 兼容性保障的。做出這類帶作用域的提案變更,是有比較大的風(fēng)險(xiǎn)的。
同時(shí)對(duì)于 Go 工具鏈的影響,也是非常大的。一改,直接都完?duì)僮恿?。確實(shí)需要盡量深思。原作者完全沒提到。
該提案,正在開放 3 周等待意見收集。很神奇,沒更多的人說話,但提案的表情給了很多個(gè)不認(rèn)同。
以上就是Go defer 去掉閉包函數(shù)及用法分析的詳細(xì)內(nèi)容,更多關(guān)于Go defer閉包函數(shù)的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
詳解Golang中channel的實(shí)現(xiàn)
channel俗稱管道,用于數(shù)據(jù)傳遞或數(shù)據(jù)共享,其本質(zhì)是一個(gè)先進(jìn)先出的隊(duì)列,使用goroutine+channel進(jìn)行數(shù)據(jù)通訊簡(jiǎn)單高效,同時(shí)也線程安全,本文就給大家講講Golang中channel的實(shí)現(xiàn),需要的朋友可以參考下2023-09-09golang的time包:秒、毫秒、納秒時(shí)間戳輸出方式
這篇文章主要介紹了golang的time包:秒、毫秒、納秒時(shí)間戳輸出方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2020-12-12深入理解gorm如何和數(shù)據(jù)庫(kù)建立連接
這篇文章主要為大家詳細(xì)介紹了gorm如何和數(shù)據(jù)庫(kù)建立連接,文中的示例代碼講解詳細(xì),對(duì)我們深入了解GO語(yǔ)言有一定的幫助,需要的小伙伴可以參考下2023-11-11Golang標(biāo)準(zhǔn)庫(kù)unsafe源碼解讀
這篇文章主要為大家介紹了Golang標(biāo)準(zhǔn)庫(kù)unsafe源碼解讀,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-08-08