日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

Go 还是需要泛型的

發(fā)布時(shí)間:2024/4/11 编程问答 28 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Go 还是需要泛型的 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

Go 語言之父早期提到過?less is more[1]?的哲學(xué),可惜社區(qū)里有不少人被帶偏了。

每次 Go 增加語法上的新特性、新功能,就會(huì)有原教旨主義者跳出來扔出一句 less is more(或者也可能是大道至簡(jiǎn)),揚(yáng)長(zhǎng)而去,留下風(fēng)中凌亂的你。

即使到了官方已經(jīng)確定要增加泛型功能的 2020 年,依然有人煞有介事地寫文章說為什么?go doesn't need generics[2],作為理智的 Gopher,最好不要對(duì)別人的結(jié)論盡信,至少要看看其它語言社區(qū)怎么看待這件事情。

Java 社區(qū)是怎么理解泛型的必要性的呢?

簡(jiǎn)而言之,泛型使類型(類和接口)能夠在定義類、接口和方法時(shí)成為參數(shù)。就像我們更熟悉的在方法聲明中使用的形式參數(shù)一樣,類型參數(shù)為你提供了一種用不同的輸入重復(fù)使用相同代碼的方法。不同的是,形式參數(shù)的輸入是值,而類型參數(shù)的輸入是類型。

與非泛型代碼相比,使用泛型的代碼有很多好處。

  • 在編譯時(shí)進(jìn)行強(qiáng)類型檢查。Java 編譯器對(duì)泛型代碼進(jìn)行強(qiáng)類型檢查,如果代碼違反類型安全就會(huì)報(bào)錯(cuò)。編譯時(shí)的錯(cuò)誤比運(yùn)行時(shí)的錯(cuò)誤更易修復(fù)。

  • 消除類型轉(zhuǎn)換。下面這段代碼片段在沒有泛型時(shí),需要類型轉(zhuǎn)換:

List?list?=?new?ArrayList(); list.add("hello"); String?s?=?(String)?list.get(0);

用泛型重寫,代碼不再需要進(jìn)行類型轉(zhuǎn)換:

List<String>?list?=?new?ArrayList<String>(); list.add("hello"); String?s?=?list.get(0);???//?no?cast
  • 程序員可以編寫泛型算法 使用泛型可以實(shí)現(xiàn)在不同類型上都可以工作的泛型算法的同時(shí),保證類型安全性。

Gopher 可能對(duì)“類型安全”不太熟悉,舉個(gè)例子,我們可以用 gods 庫來實(shí)現(xiàn)下面的數(shù)據(jù)結(jié)構(gòu)。

package?mainimport?("fmt"sll?"github.com/emirpasic/gods/lists/singlylinkedlist" )func?main()?{list?:=?sll.New()list.Add("a")?????????????????????//?["a"] }

我們的本意是實(shí)現(xiàn)一個(gè) string 的單鏈表,但是通用的數(shù)據(jù)結(jié)構(gòu)庫沒有辦法阻止用戶向該 list 內(nèi)插入非 string 類型的值,比如用戶可以這樣:

?list?:=?sll.New()list.Add("a")?????????????????????//?["a"]list.Add(2)???????????????????????//?["a",?2]

這顯然不是我們想要的結(jié)果。

可見泛型最常見的場(chǎng)景是在類型安全的前提下實(shí)現(xiàn)算法流程,對(duì)于 Go 來說,我們使用的數(shù)據(jù)結(jié)構(gòu)和算法來源有兩個(gè)地方:container 標(biāo)準(zhǔn)庫、第三方數(shù)據(jù)結(jié)構(gòu)庫,如?gods[3]?。

和我們前面舉的例子一樣,標(biāo)準(zhǔn)庫的通用 container 的大多接口也是接收空 interface{},或返回空 interface{}:

package?mainimport?("container/list" )func?main()?{l?:=?list.New()l.PushBack(4)l.PushFront("bad?value") }

做不到類型安全的話,那么用戶代碼就可能在運(yùn)行期間發(fā)生斷言產(chǎn)生的 panic/error。除了容器的功能容易被破壞,類似下面的 bug 也挺容易出現(xiàn)的:

package?mainimport?"fmt"type?mystring?stringfunc?main()?{var?a?interface{}?=?"abc"var?b?interface{}?=?mystring("abc")fmt.Println(a?==?b) }

社區(qū)的其它嘗試

社區(qū)曾經(jīng)有一些靠代碼生成實(shí)現(xiàn)的泛型庫,如genny[4],其本質(zhì)是使用文本替換來實(shí)現(xiàn)多種類型的代碼生成。

genny 使用也比較簡(jiǎn)單,比如 example 里的例子:

package?queueimport?"github.com/cheekybits/genny/generic"//?NOTE:?this?is?how?easy?it?is?to?define?a?generic?type type?Something?generic.Type//?SomethingQueue?is?a?queue?of?Somethings. type?SomethingQueue?struct?{items?[]Something }func?NewSomethingQueue()?*SomethingQueue?{return?&SomethingQueue{items:?make([]Something,?0)} } func?(q?*SomethingQueue)?Push(item?Something)?{q.items?=?append(q.items,?item) } func?(q?*SomethingQueue)?Pop()?Something?{item?:=?q.items[0]q.items?=?q.items[1:]return?item }

cat source.go | genny gen "Something=string"

//?This?file?was?automatically?generated?by?genny. //?Any?changes?will?be?lost?if?this?file?is?regenerated. //?see?https://github.com/cheekybits/gennypackage?queue//?StringQueue?is?a?queue?of?Strings. type?StringQueue?struct?{items?[]string }func?NewStringQueue()?*StringQueue?{return?&StringQueue{items:?make([]string,?0)} } func?(q?*StringQueue)?Push(item?string)?{q.items?=?append(q.items,?item) } func?(q?*StringQueue)?Pop()?string?{item?:=?q.items[0]q.items?=?q.items[1:]return?item }

想實(shí)現(xiàn)多種類型的結(jié)構(gòu)就在生成代碼時(shí)傳入多種類型就可以了。

這種做法和人們調(diào)侃 Go 泛型時(shí)使用的?gif[5]?本質(zhì)上也沒什么區(qū)別。

語言的原生支持能讓我們省事,并且也能在實(shí)現(xiàn)上更加嚴(yán)謹(jǐn)。

在 《Rise and Fall of Software Recipes》一書中,有這么一個(gè)故事:

Among the recent projects failing because (or despite) of strong processes, Obamacare is a telling example. It involves 50 contractors, has cost fortunes, was delivered late and crippled with bugs. It was developed using a typical waterfall process, and if only because of that, the Agile community started howling, claiming that they would have made the project a success[Healthcare.gov failure].

And when an Agile project fails like Universal Credit in Great-Britain[UniversalCredit] [NAO2013], even when the full report states that the lack of detailed blueprint – typical of Agile methodologies – was one of the factors that caused the failure, common Agile wisdom says it is because it was not applied properly, or should I say, not Agile enough.

簡(jiǎn)而言之,就是敏捷大師們其實(shí)非常雙標(biāo),他們給出的方法論也不一定靠譜,反正成功了就是大師方法得當(dāng),失敗了就是我們執(zhí)行不力沒有學(xué)到精髓。正著說反著說都有道理。

再看看現(xiàn)在的 Go 社區(qū),buzzwords 也很多,如果一個(gè)特性大師不想做,那就是 less is more。如果一個(gè)特性大師想做,那就是 orthogonal,非常客觀。

對(duì)于不想迷信大師的 Gopher 來說,多聽聽批評(píng)意見沒壞處:go is not good[6]。

[1]

less is more:?https://en.wikipedia.org/wiki/Less_is_more

[2]

go doesn't need generics:?https://dzone.com/articles/go-doesnt-need-generics

[3]

gods:?https://github.com/emirpasic/gods

[4]

genny:?https://github.com/cheekybits/genny

[5]

gif:?https://twitter.com/yogthos/status/883058510275149826

[6]

go is not good:?https://github.com/ksimka/go-is-not-good

總結(jié)

以上是生活随笔為你收集整理的Go 还是需要泛型的的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。