日韩无码专区无码一级三级片|91人人爱网站中日韩无码电影|厨房大战丰满熟妇|AV高清无码在线免费观看|另类AV日韩少妇熟女|中文日本大黄一级黄色片|色情在线视频免费|亚洲成人特黄a片|黄片wwwav色图欧美|欧亚乱色一区二区三区

RELATEED CONSULTING
相關咨詢
選擇下列產(chǎn)品馬上在線溝通
服務時間:8:30-17:00
你可能遇到了下面的問題
關閉右側工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營銷解決方案
為什么Go的泛型一拖再拖?

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

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

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

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

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

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

什么是泛型

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

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

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

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

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

為什么需要泛型

這時候可能會有人說,沒有泛型也可以啊...感覺寫業(yè)務代碼沒什么影響,與其搞泛型不如搞好 errors(具體新消息可參見:重磅:Go errors 將不會有任何進一步的改進計劃)。

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

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

另外同時單從語言層面來講,泛型支持是一個必然事件了,因為泛型的存在對解決特定領域的問題存在一定的意義。

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

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

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

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

 
 
 
 
  1. F("煎魚", 233)

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

而反過來看真 “泛型” 的實際使用,編譯器會保證泛型函數(shù)的入?yún)⒑统鰠⒈仨殲橥活愋?,有強制性的檢驗:

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

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

總體來講,泛型相較接口有如下優(yōu)點:

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

過去:為什么那么久都沒有泛型

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

變相來看,可能其會認為 ”Go 都已經(jīng) 11 歲了,2020 年了居然還沒有泛型?”。

這顯然是不對的,因為泛型本質(zhì)上并不是絕對的必需品,更不是 Go 語言的早期目標,因此在過往的發(fā)展階段沒有過多重視這一點,而是把精力放在了其他 feature 上。

另外 Go 語言在以往其實進行過大量的泛型 proposal 試驗,基本時間線(via @changkun)如下:

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

現(xiàn)在:Go 泛型

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

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

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

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

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

函數(shù)簽名

咋一看,變量 T 的這個關鍵字 any 是什么?早期泛型你可能有聽說合約(Contract),難道這就是合約。其實嚴格意義上來講并不是,因為為了更一步簡化語法,合約在 2020.06.07 已經(jīng)正式移除。

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

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

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

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

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

泛型的戰(zhàn)爭

為什么不用尖括號

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

思考問題我們不只看表面,官方說不行,那么我們可以倒推來看,看看 Go 語言就用尖括號:

 
 
 
 
  1. func print(list []T) {
  2. print(numbers)
  3. print(strings)
  4. print(floats)

普通的函數(shù)聲明看上去似乎結構清晰,沒有什么大問題的。接著往下看:

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

我們繼續(xù)把代碼演進一下,簡潔一點:

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

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

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

又或是:

 
 
 
 
  1. a, b := w(z)

從上述代碼來看,使用尖括號難以分別,因為沒有類型信息,就無法確定賦值的右側是一對表達式 w < x和y > (z),還是返回兩個結果值 w(z) 的泛型函數(shù)實例化和調(diào)用,其存在歧義。

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

為什么不用括號

其實最早 Go 泛型的版本是使用了括號的模式,雖然能用,但是用括號會引入新的解析歧義。例如:

 
 
 
 
  1. var f func(x(T))

從語法上來講,你無法識別他是未命名參數(shù)的 x(T) 函數(shù),還是類型名為參數(shù)的 (T) 函數(shù)。

同時 Go 語言還存在強制類型轉換這一語法,假設代碼是 []T(v1) 和 []T(v2){} ,那么你在開括號處,就無法得知其是否代表類型轉換。

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

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

函數(shù)入?yún)ⅰ⒎盒?、返回值聲明均都是括號,造成了語義不清,這顯然也是不合理的。

為什么不用書名號(??)

想的美,并不想使用非 ASCII,未來更沒打算支持。

總結

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

同時我們還針對業(yè)界常見的一些疑問,例如接口和泛型的區(qū)別,泛型的歷史,泛型的尖括號/括號/書名號之爭進行了解釋和說明。

最后我們回答一下最開始的疑問,”為什么 Go 的泛型一拖再拖“,主要如下:

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

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

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

到底拖到什么時候

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

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

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

最后,靈魂拷問:你對 Go 語言的泛型又有什么想法和意見呢,一起留言討論吧。


本文名稱:為什么Go的泛型一拖再拖?
網(wǎng)站鏈接:http://m.5511xx.com/article/cdjiogp.html