成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

為什么 Go 的泛型一拖再拖?

開(kāi)發(fā) 前端
信息匯總來(lái)看,Go 泛型這幾年會(huì)出,但大體來(lái)講現(xiàn)在 Go 泛型又又又推遲了。好家伙,我最早了解到時(shí)是考慮 Go1.16 釋出,后面又推到了 Go1.17,接著現(xiàn)在又延期到了 Go1.18 了(2021 年底)。

大家好,我是從不放鴿子的煎魚。

前段時(shí)間 Go 語(yǔ)言的泛型討論頻頻出現(xiàn)在各微信群,且又沖上了國(guó)內(nèi)外各大文章的 “頭條”:

信息匯總來(lái)看,Go 泛型這幾年會(huì)出,但大體來(lái)講現(xiàn)在 Go 泛型又又又推遲了。好家伙,我最早了解到時(shí)是考慮 Go1.16 釋出,后面又推到了 Go1.17,接著現(xiàn)在又延期到了 Go1.18 了(2021 年底)。

看到了信息的表象后,再想想為什么泛型 “這件事情” 突然醒目起來(lái)了,其原因之一是由官方 Go,11 歲[1] 的博文所引爆的。

同時(shí)近日舉辦的 GopherCon2020 大會(huì),Robert Griesemer 分享的 Typing [Generic] Go。更正式的讓 Go 泛型更面向了大眾,也側(cè)面的說(shuō)明官方認(rèn)為其已經(jīng)到達(dá)了一個(gè)新的階段了,進(jìn)入最終實(shí)現(xiàn)階段。

事不宜遲,既然官方都已經(jīng)摩拳擦掌了,我們的學(xué)習(xí)之路也得跟上,因此本文將會(huì)介紹 Go 泛型現(xiàn)在的情況,并通過(guò)在介紹過(guò)程中不斷思考最后得出一個(gè)為什么。

什么是泛型

泛型程序設(shè)計(jì)(generic programming)是程序設(shè)計(jì)語(yǔ)言的一種風(fēng)格或范式。泛型允許程序員在強(qiáng)類型語(yǔ)言中編寫代碼時(shí),使用一些以后才確定的類型,其在真正實(shí)例化時(shí)才會(huì)為這些參數(shù)指確定類型。

另外各語(yǔ)言和其編譯器、運(yùn)行環(huán)境對(duì)泛型的支持均不一樣,因此需要針對(duì)來(lái)辯證。

簡(jiǎn)單來(lái)講,泛型就是參數(shù)化多態(tài)。其可根據(jù)實(shí)參類型生成不同的版本,支持任意數(shù)量的調(diào)用:

  1. func F(a, b T) T{ return a+b } 
  2.  
  3. // T 為 int 
  4. F(1, 2) 
  5.  
  6. // T 為 string 
  7. F("1""2"

在編譯時(shí)期編譯器便確定其 T 的入?yún)㈩愋汀_@也是 Go 泛型實(shí)現(xiàn)的要求之一 “編譯時(shí)類型安全”。

為什么需要泛型

這時(shí)候可能會(huì)有人說(shuō),沒(méi)有泛型也可以啊...感覺(jué)寫業(yè)務(wù)代碼沒(méi)什么影響,與其搞泛型不如搞好 errors(具體新消息可參見(jiàn):重磅:Go errors 將不會(huì)有任何進(jìn)一步的改進(jìn)計(jì)劃)。

但泛型是有其所需的場(chǎng)景,最常見(jiàn)的是像基礎(chǔ)庫(kù)在處理獲取配置中心數(shù)據(jù)時(shí),就要處理類型,時(shí)常遇到下述場(chǎng)景:

 

 

手寫一個(gè) “泛型”如果使用接口(interface)類型來(lái)做,也得 switch.(type) 枚舉出所有的基礎(chǔ)類型。這顯然并不合理,也沒(méi)法做太復(fù)雜的邏輯,而且所支持的類型還泄露。

 

另外同時(shí)單從語(yǔ)言層面來(lái)講,泛型支持是一個(gè)必然事件了,因?yàn)榉盒偷拇嬖趯?duì)解決特定領(lǐng)域的問(wèn)題存在一定的意義。

接口和泛型有什么區(qū)別

在上面我們有提到接口(interface)類型,這時(shí)候就出現(xiàn)了泛型的第二個(gè)經(jīng)典問(wèn)題。那就是 “接口和泛型有什么區(qū)別?”,為什么不用接口來(lái)實(shí)現(xiàn) “泛型”:

  1. type T interface { ... } 
  2. func F(a, b T) T { return a+b } 

也像這么一回事,但在這里存在一個(gè)致命的缺陷。那就是接口的入?yún)⒑统鰠⒕梢栽谶\(yùn)行時(shí)表現(xiàn)為不同的類型:

  1. F("煎魚", 233) 

要做好,還得依靠?jī)?nèi)部去對(duì)參數(shù)進(jìn)行斷言,否則作為 string 類型的煎魚又如何和 int 類型的 233 相加呢,那是必然報(bào)錯(cuò)的。

而反過(guò)來(lái)看真 “泛型” 的實(shí)際使用,編譯器會(huì)保證泛型函數(shù)的入?yún)⒑统鰠⒈仨殲橥活愋停袕?qiáng)制性的檢驗(yàn):

  1. // 報(bào)錯(cuò):type checking failed for main 
  2. F("煎魚", 233) 
  3.  
  4. // 必須為同一類型,才能正常運(yùn)行 
  5. F(666, 233) 

兩者存在本質(zhì)上的區(qū)別,泛型會(huì)更安全,能夠保證編譯早期就發(fā)現(xiàn)錯(cuò)誤,而不是等到運(yùn)行時(shí)(并且可能會(huì)存在隱性的 BUG)。

總體來(lái)講,泛型相較接口有如下優(yōu)點(diǎn):

  • 更安全:編譯早期就能發(fā)現(xiàn)錯(cuò)誤。
  • 性能好:靜態(tài)類型。

過(guò)去:為什么那么久都沒(méi)有泛型

前幾段在社區(qū)的微信群看到一位小伙伴吐槽 “Go 語(yǔ)言居然沒(méi)有泛型?”。

變相來(lái)看,可能其會(huì)認(rèn)為 ”Go 都已經(jīng) 11 歲了,2020 年了居然還沒(méi)有泛型?”。

這顯然是不對(duì)的,因?yàn)榉盒捅举|(zhì)上并不是絕對(duì)的必需品,更不是 Go 語(yǔ)言的早期目標(biāo),因此在過(guò)往的發(fā)展階段沒(méi)有過(guò)多重視這一點(diǎn),而是把精力放在了其他 feature 上。

另外 Go 語(yǔ)言在以往其實(shí)進(jìn)行過(guò)大量的泛型 proposal 試驗(yàn),基本時(shí)間線(via @changkun)如下:

雖然偶有中斷,但仔細(xì)一看,2010 年就嘗試過(guò),現(xiàn)在 2020 年了,也是很勵(lì)志了,顯然官方也是在尋路和嘗試的過(guò)程中,但一直沒(méi)有找到相較好的方案,大多都存在問(wèn)題,社區(qū)對(duì)方案的爭(zhēng)議也不斷。

現(xiàn)在:Go 泛型

泛型嘗鮮的方式有兩種方式。線上 Ian Lance Taylor 提供了一個(gè)在線編譯的 go2go[2]:

 

另外一種是線下,也就在本地安裝 Go 的特定分支版本:

  1. $ git clone https://github.com/golang/go 
  2. $ git checkout dev.go2go 
  3. $ cd src && ./all.bash 

不過(guò)這種本地安裝的方法會(huì)耗時(shí)比較久,初步嘗試的話建議使用 go2go 就可以了。

而在嘗鮮時(shí),可以看到在代碼塊中聲明了一個(gè) Print 方法,其函數(shù)簽名主體分為三部分:

 

 

函數(shù)簽名

 

咋一看,變量 T 的這個(gè)關(guān)鍵字 any 是什么?早期泛型你可能有聽(tīng)說(shuō)合約(Contract),難道這就是合約。其實(shí)嚴(yán)格意義上來(lái)講并不是,因?yàn)闉榱烁徊胶?jiǎn)化語(yǔ)法,合約在 2020.06.07 已經(jīng)正式移除。

其已改頭換面,現(xiàn)在只需要寫參數(shù)化的 interface。而上述的 any 關(guān)鍵字是一個(gè)預(yù)定義的類型約束,聲明后將允許任何類型用作類型實(shí)參,并且允許函數(shù)使用用于任何類型的操作。

從語(yǔ)法分析的角度來(lái)講,Print 方法一共包含了如下屬性(從左到右):

  • type list:聲明了入?yún)⒌念愋土斜頌橐粋€(gè) T 變量,其可以傳任意類型的參數(shù)。
  • parameter list:聲明了入?yún)⒌膮?shù)列表為 T 變量的切片,且形參為 s。
  • return type list:聲明了函數(shù)的返回參數(shù)列表。

上述函數(shù)簽名便是一個(gè) Go 泛型的基本樣子,由于本文并不是 CRUD 泛型,便不展開(kāi)案例(且現(xiàn)有泛型還不成熟)。

若大家有興趣,強(qiáng)烈建議閱讀提案:Type Parameters - Draft Design[3]。

泛型的戰(zhàn)爭(zhēng)

為什么不用尖括號(hào)

在社區(qū)中很多同學(xué)在討論的一個(gè)問(wèn)題,那就是 “為什么 Go 泛型不像 C++ 和 Java 那樣使用尖括號(hào)?,也出現(xiàn)了 “Go 一直標(biāo)榜業(yè)界工程實(shí)踐類的榜樣,為什么就是不用尖括號(hào)” 的言論?

思考問(wèn)題我們不只看表面,官方說(shuō)不行,那么我們可以倒推來(lái)看,看看 Go 語(yǔ)言就用尖括號(hào):

  1. func print<type T>(list []T) { 
  2.  
  3. print<int>(numbers) 
  4. print<string>(strings) 
  5. print<float64>(floats) 

普通的函數(shù)聲明看上去似乎結(jié)構(gòu)清晰,沒(méi)有什么大問(wèn)題的。接著往下看:

  1. a := w < xb := y > (z) 

我們繼續(xù)把代碼演進(jìn)一下,簡(jiǎn)潔一點(diǎn):

  1. a, b := w < x, y > (z) 

這時(shí)候就犯難了,不僅編譯器難以解析,人也很難判別,到底指的是:

  1. a := w < xb := y > (z) 

又或是:

  1. a, b := w(z) 

從上述代碼來(lái)看,使用尖括號(hào)難以分別,因?yàn)闆](méi)有類型信息,就無(wú)法確定賦值的右側(cè)是一對(duì)表達(dá)式 w < x和y > (z),還是返回兩個(gè)結(jié)果值 w(z) 的泛型函數(shù)實(shí)例化和調(diào)用,其存在歧義。

要解決還要引入新的約束,會(huì)破壞 Go1 的兼容性承諾,這顯然是不合理的。

為什么不用括號(hào)

其實(shí)最早 Go 泛型的版本是使用了括號(hào)的模式,雖然能用,但是用括號(hào)會(huì)引入新的解析歧義。例如:

  1. var f func(x(T)) 

從語(yǔ)法上來(lái)講,你無(wú)法識(shí)別他是未命名參數(shù)的 x(T) 函數(shù),還是類型名為參數(shù)的 (T) 函數(shù)。

同時(shí) Go 語(yǔ)言還存在強(qiáng)制類型轉(zhuǎn)換這一語(yǔ)法,假設(shè)代碼是 []T(v1) 和 []T(v2){} ,那么你在開(kāi)括號(hào)處,就無(wú)法得知其是否代表類型轉(zhuǎn)換。

甚至在函數(shù)的完整聲明上,我們都會(huì)感到困惑:

  1. func F(T any)(v T)(r1, r2 T) 

函數(shù)入?yún)ⅰ⒎盒汀⒎祷刂德暶骶际抢ㄌ?hào),造成了語(yǔ)義不清,這顯然也是不合理的。

為什么不用書名號(hào)(«»)

想的美,并不想使用非 ASCII,未來(lái)更沒(méi)打算支持。

總結(jié)

在本文中我們從多個(gè)維度介紹了 Go 泛型的相關(guān)內(nèi)容,既了解到了上段時(shí)間 Go 泛型再度火爆的信息來(lái)源是什么。也知道了 Go 泛型是什么,與接口的區(qū)別。

同時(shí)我們還針對(duì)業(yè)界常見(jiàn)的一些疑問(wèn),例如接口和泛型的區(qū)別,泛型的歷史,泛型的尖括號(hào)/括號(hào)/書名號(hào)之爭(zhēng)進(jìn)行了解釋和說(shuō)明。

最后我們回答一下最開(kāi)始的疑問(wèn),”為什么 Go 的泛型一拖再拖“,主要如下:

  • Go 語(yǔ)言的早期目標(biāo)(工作重點(diǎn))并不是泛型。
  • Go 語(yǔ)言在 2010-2020 年都有間斷在做 Go 泛型的 proposal,但總是 ”失敗“,在不斷地吸收經(jīng)驗(yàn)。
  • Go 語(yǔ)言社區(qū)的意見(jiàn)反饋是真的多,單用什么符號(hào)表示泛型,不想要泛型都爭(zhēng)論不休。
  • Go 語(yǔ)言的泛型現(xiàn)在還不成熟,很多細(xì)節(jié)其實(shí)并沒(méi)有支持好。

很顯然,在保證 Go1 向后兼容性的同時(shí),Go 官方也不想直接妥協(xié)出一個(gè)隨便的方案,因此總是不斷地在改進(jìn)。

隨著 Go 語(yǔ)言的在業(yè)內(nèi)的不斷應(yīng)用,泛型也和 errors 一樣被推上風(fēng)頭浪尖。

到底拖到什么時(shí)候

那 Go 泛型到底什么時(shí)候出呢?前段時(shí)間也向歐神(@changkun)了解到:

在 GopherCon 2020 Go Team AMA 時(shí),russ cox 有聊到相關(guān)問(wèn)題,表示在明年年底要能有生產(chǎn)環(huán)境的試用版上線,這是一個(gè)管理目標(biāo)。

但具體真正的時(shí)間線肯定是要看泛型的實(shí)現(xiàn)者:robert 和 keith,可以多多關(guān)注他們,就能拿到一手信息,且可以確定的是 Go 泛型明年二月之前是不會(huì)有生產(chǎn)可用的試用版。

最后,靈魂拷問(wèn):你對(duì) Go 語(yǔ)言的泛型又有什么想法和意見(jiàn)呢,一起留言討論吧。

責(zé)任編輯:未麗燕 來(lái)源: 腦子進(jìn)煎魚了
相關(guān)推薦

2020-03-02 14:18:33

程序員技能開(kāi)發(fā)者

2020-09-27 16:40:29

程序員技術(shù)開(kāi)發(fā)

2009-02-12 14:41:00

安騰英特爾惠普

2021-05-27 19:39:58

MWC21世界移動(dòng)大會(huì)移動(dòng)通信

2015-02-04 10:46:59

AppleWatchuber

2009-06-02 09:16:58

Firefox瀏覽器

2012-06-28 10:48:31

設(shè)計(jì)交互設(shè)計(jì)

2021-09-29 18:17:30

Go泛型語(yǔ)言

2011-01-27 09:16:04

微軟云計(jì)算

2018-11-30 16:19:03

App啟動(dòng)SDK

2025-02-03 12:33:08

2023-09-06 12:57:11

AI訓(xùn)練

2021-12-05 23:45:23

Go泛型Maps

2023-09-18 09:00:59

2010-03-10 09:54:38

APC

2011-03-01 10:19:10

2011-07-21 15:13:43

機(jī)房數(shù)據(jù)中心服務(wù)器

2015-12-01 10:00:21

2023-11-29 08:19:45

Go泛型缺陷

2024-10-28 00:40:49

Go語(yǔ)法版本
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)

主站蜘蛛池模板: 一区二区三区四区不卡 | 成人在线视频免费观看 | 欧美日韩在线成人 | 欧美日韩淫片 | 精品九九九 | 成人久久久 | 日本一区二区在线视频 | 中文字幕国产视频 | 精品久久久久久久久久久久 | 黑人精品欧美一区二区蜜桃 | 午夜影院在线观看 | 一区二区成人在线 | 一级在线观看 | 欧美国产亚洲一区二区 | 欧美日韩亚洲在线 | 国产999精品久久久久久 | 欧美精品国产一区二区 | 欧美一区二区在线免费观看 | 久久久久久九九九九九九 | 欧美日韩亚洲三区 | 欧美在线高清 | 色播av | 久久久久se| a看片| 国产精品永久 | 美女二区 | 日本久久www成人免 成人久久久久 | 91精品国产乱码麻豆白嫩 | 欧美 日韩 国产 成人 | 欧美久久久久久久 | 欧美日韩在线一区二区三区 | 中文字幕国产 | 久久久久久毛片免费观看 | 欧美日韩国产在线观看 | 在线观看视频91 | 国产综合在线视频 | 久久精品亚洲精品 | 欧洲色综合 | 青青草av | 亚洲视频在线看 | 夜夜摸夜夜操 |