2 回答

TA貢獻(xiàn)2041條經(jīng)驗(yàn) 獲得超4個(gè)贊
William B. Yager 的 博客文章提醒了為什么 Go 中存在的“通用”部分是不夠的:
你可以很容易地編寫泛型函數(shù)。
假設(shè)您想編寫一個(gè)函數(shù),為可以散列的對(duì)象打印一個(gè)散列碼。您可以定義一個(gè)接口,允許您使用靜態(tài)類型安全保證來執(zhí)行此操作,如下所示:
type Hashable interface {
Hash() []byte
}
func printHash(item Hashable) {
fmt.Println(item.Hash())
}
現(xiàn)在,您可以向 提供任何Hashable對(duì)象printHash,并且還可以進(jìn)行靜態(tài)類型檢查。這很好。
如果你想寫一個(gè)通用的數(shù)據(jù)結(jié)構(gòu)怎么辦?
讓我們寫一個(gè)簡(jiǎn)單的鏈表。在 Go 中編寫通用數(shù)據(jù)結(jié)構(gòu)的慣用方法是:
(這里只是開始)
type LinkedList struct {
value interface{}
next *LinkedList
}
func (oldNode *LinkedList) prepend(value interface{}) *LinkedList {
return &LinkedList{value, oldNode}
}
在 Go 中構(gòu)建通用數(shù)據(jù)結(jié)構(gòu)的“正確”方法是將事物轉(zhuǎn)換為頂級(jí)類型,然后將它們放入數(shù)據(jù)結(jié)構(gòu)中。這就是 Java 過去的工作方式,大約在 2004 年。然后人們意識(shí)到這完全違背了類型系統(tǒng)的目的。
當(dāng)您擁有這樣的數(shù)據(jù)結(jié)構(gòu)時(shí),您將完全消除類型系統(tǒng)提供的任何好處。例如,這是完全有效的代碼:
node := tail(5).prepend("Hello").prepend([]byte{1,2,3,4})
所以這就是為什么,如果你想保留類型系統(tǒng)的好處,你必須使用一些代碼生成,為你的特定類型生成樣板代碼。
該gen項(xiàng)目是這種方法的一個(gè)例子:
gen在開發(fā)時(shí)使用命令行為您的類型生成代碼。
gen不是進(jìn)口;生成的源代碼成為您項(xiàng)目的一部分,并且不需要任何外部依賴項(xiàng)。
2017 年 6 月更新:Dave Cheney 在他的文章“ Simplicity Debt ”和“ Simplicity Debt Redux ”中詳細(xì)說明了 Go 泛型的含義。
由于Go 2.0 現(xiàn)在在核心團(tuán)隊(duì)層面被積極討論,Dave 指出泛型涉及到什么,那就是:
錯(cuò)誤處理:泛型將允許monadic 錯(cuò)誤處理,這意味著您需要在其余部分之上了解 monad:?jiǎn)⒂锰幚碛?jì)算管道而不是在每次函數(shù)調(diào)用后檢查錯(cuò)誤。
但是:你需要了解 monad!
集合:促進(jìn)自定義集合類型,無需接口裝箱和類型斷言。{}
但這留下了如何處理內(nèi)置切片和地圖類型的問題。
切片:它是否會(huì)消失,如果是這樣,這將如何影響諸如處理調(diào)用結(jié)果之類的常見操作io.Reader.Read?
如果切片沒有消失,是否需要添加運(yùn)算符重載,以便用戶定義的集合類型可以實(shí)現(xiàn)切片運(yùn)算符?
Vector:Go 的類似 Pascal 的數(shù)組類型具有在編譯時(shí)已知的固定大小。如何在不訴諸不安全黑客的情況下實(shí)現(xiàn)可增長(zhǎng)的向量?
迭代器:你真正想要做的是在數(shù)據(jù)庫結(jié)果和網(wǎng)絡(luò)請(qǐng)求上組合迭代器。
簡(jiǎn)而言之,來自流程外部的數(shù)據(jù)——當(dāng)數(shù)據(jù)位于流程之外時(shí),檢索它可能會(huì)失敗。
在這種情況下,您有一個(gè)選擇,您的Iterable接口是否返回一個(gè)值、一個(gè)值和一個(gè)錯(cuò)誤,或者您可能沿著選項(xiàng)類型路線走下去。
不變性:將函數(shù)參數(shù)標(biāo)記為的能力const是不夠的,因?yàn)殡m然它限制了接收者改變值,但它并沒有禁止調(diào)用者這樣做,這是我今天在 Go 程序中看到的大多數(shù)數(shù)據(jù)競(jìng)爭(zhēng)。
也許 Go 需要的不是不變性,而是所有權(quán)語義。
正如Russ Cox在“我的 2017 年 Go 決議”中所寫:
今天,也有更新的嘗試可以學(xué)習(xí),包括 Dart、Midori、Rust 和 Swift。
最新的討論是Go 問題 15292:它還引用了“ Go 泛型討論摘要”。
- 2 回答
- 0 關(guān)注
- 319 瀏覽
添加回答
舉報(bào)