Go 正在發(fā)生變化?從泛型到迭代器的愛(ài)恨
大家好,我是煎魚(yú)。
前段時(shí)間 Kris Brandow 和嘉賓 Ian Lopshire 在播客中針對(duì)《Go 的發(fā)展方向錯(cuò)了嗎?》這個(gè)命題進(jìn)行了深入討論,還探討了 Go 語(yǔ)言的最新變化及其發(fā)展方向,重點(diǎn)涉及泛型和新版本加入的迭代器功能。
社區(qū)對(duì)這些特性的反應(yīng)各不相同:
1、一些開(kāi)發(fā)者認(rèn)為增加的新特性違背了 Go 語(yǔ)言原本簡(jiǎn)潔的設(shè)計(jì)理念。
2、另一些則期待這些功能為開(kāi)發(fā)帶來(lái)的靈活性和便利性。
本文將結(jié)合兩位嘉賓的觀點(diǎn),深入分析這些功能背后的技術(shù)細(xì)節(jié)及其對(duì) Go 語(yǔ)言生態(tài)系統(tǒng)的影響。
泛型:必要的復(fù)雜性
Go 語(yǔ)言一直以來(lái)因其簡(jiǎn)單和一致性備受贊譽(yù),但隨著應(yīng)用場(chǎng)景的拓寬和開(kāi)發(fā)需求的增加,語(yǔ)言的功能擴(kuò)展變得不可避免。
泛型作為 Go 1.18 版本中最重要的新增特性,顯著地豐富了開(kāi)發(fā)者的工具箱,也因此引起了社區(qū)內(nèi)外的廣泛關(guān)注與討論。
一個(gè)簡(jiǎn)單的泛型例子:
// Stack 使用泛型定義一個(gè)棧數(shù)據(jù)結(jié)構(gòu)
type Stack[T any] struct {
elements []T
}
// Push 將元素壓入棧中
func (s *Stack[T]) Push(element T) {
s.elements = append(s.elements, element)
}
// Pop 從棧中彈出元素
func (s *Stack[T]) Pop() (T, bool) {
if len(s.elements) == 0 {
var zero T
return zero, false
}
index := len(s.elements) - 1
element := s.elements[index]
s.elements = s.elements[:index]
return element, true
}
func main() {
// 創(chuàng)建一個(gè)整數(shù)類(lèi)型的棧
intStack := Stack[int]{}
intStack.Push(10)
intStack.Push(20)
fmt.Println(intStack.Pop()) // 輸出: 20, true
fmt.Println(intStack.Pop()) // 輸出: 10, true
// 創(chuàng)建一個(gè)字符串類(lèi)型的棧
stringStack := Stack[string]{}
stringStack.Push("Hello")
stringStack.Push("Go")
fmt.Println(stringStack.Pop()) // 輸出: Go, true
fmt.Println(stringStack.Pop()) // 輸出: Hello, true
}
輸出結(jié)果:
20 true
10 true
Go true
Hello true
Ian 的看法:Ian 認(rèn)為,泛型的引入確實(shí)增加了語(yǔ)言的復(fù)雜性,但這一功能的加入是必需的。他指出,盡管泛型的概念增加了學(xué)習(xí)門(mén)檻,但在很多常見(jiàn)場(chǎng)景中,泛型的使用不會(huì)顯得過(guò)于突兀。
他提到,泛型的最大優(yōu)勢(shì)在于代碼的復(fù)用性和靈活性,特別是在構(gòu)建復(fù)雜的數(shù)據(jù)結(jié)構(gòu)或工具庫(kù)時(shí),泛型能顯著減少冗余代碼,從而提升開(kāi)發(fā)效率。
例如,使用泛型可以避免為不同數(shù)據(jù)類(lèi)型編寫(xiě)重復(fù)的代碼,實(shí)現(xiàn)了一種“寫(xiě)一次,適用多處”的效果。
Ian 的觀點(diǎn)與社區(qū)的主流態(tài)度一致,開(kāi)發(fā)者們普遍認(rèn)為泛型雖然復(fù)雜,但它帶來(lái)的優(yōu)勢(shì)也是顯而易見(jiàn)的。在一個(gè)高效的編程語(yǔ)言中,泛型的支持使得 Go 的應(yīng)用場(chǎng)景更為廣泛,適用于更多復(fù)雜的項(xiàng)目和需求。
迭代器:標(biāo)準(zhǔn)化的挑戰(zhàn)
Go 1.23 版本將要加入的迭代器功能再次引起了人們對(duì)語(yǔ)言復(fù)雜性的討論。
迭代器可以提供一種標(biāo)準(zhǔn)化的遍歷集合數(shù)據(jù)的方法,有助于增強(qiáng) Go 在數(shù)據(jù)處理方面的能力。
然而,如何平衡這種增強(qiáng)功能與語(yǔ)言的簡(jiǎn)潔性是 Go 設(shè)計(jì)者們所面臨的核心挑戰(zhàn)。
一個(gè)簡(jiǎn)單的迭代器例子:
func Backward[E any](s []E "E any") iter.Seq2[int, E] {
return func(yield func(int, E) bool) {
for i := len(s) - 1; i >= 0; i-- {
if !yield(i, s[i]) {
return
}
}
}
}
func main() {
sl := []string{"腦子", "進(jìn)", "煎魚(yú)", "了"}
for i, s := range Backward(sl) {
fmt.Printf("%d: %s\n", i, s)
}
}
輸出結(jié)果:
3: 了
2: 煎魚(yú)
1: 進(jìn)
0: 腦子
Kris 的意見(jiàn):Kris 對(duì) Go1.23 加入的迭代器功能持謹(jǐn)慎樂(lè)觀的態(tài)度。他指出,盡管迭代器提供了一種優(yōu)雅的解決方案,尤其是在處理大型數(shù)據(jù)集合或流式數(shù)據(jù)時(shí)非常有效,但其函數(shù)簽名的復(fù)雜性和潛在的學(xué)習(xí)曲線讓他感到擔(dān)憂(yōu)。
他認(rèn)為,標(biāo)準(zhǔn)化的迭代器或許能夠減少開(kāi)發(fā)者在處理不同數(shù)據(jù)結(jié)構(gòu)時(shí)的心智負(fù)擔(dān),但必須確保這一特性不會(huì)偏離 Go 簡(jiǎn)潔的設(shè)計(jì)哲學(xué)。
使用場(chǎng)景:在數(shù)據(jù)科學(xué)或機(jī)器學(xué)習(xí)領(lǐng)域,迭代器是一種常見(jiàn)的模式,能夠高效地遍歷大量數(shù)據(jù),進(jìn)行批量處理或數(shù)據(jù)流分析。迭代器的引入無(wú)疑拓展了 Go 的應(yīng)用邊界,使其能夠更好地勝任此類(lèi)需求。
Go 未來(lái)方向:復(fù)雜性與簡(jiǎn)潔性的平衡
Go 語(yǔ)言的發(fā)展一直遵循著一條清晰的設(shè)計(jì)哲學(xué),即 “簡(jiǎn)潔優(yōu)先”。
然而,隨著需求的變化和用戶(hù)數(shù)量的增長(zhǎng),Go 的設(shè)計(jì)團(tuán)隊(duì)也在不斷權(quán)衡如何在保留語(yǔ)言簡(jiǎn)潔性的同時(shí),為開(kāi)發(fā)者提供更多的工具和靈活性。
在討論中,Kris 和 Ian 一致認(rèn)為,語(yǔ)言功能的增加不可避免會(huì)引入一些復(fù)雜性,而這種復(fù)雜性是否值得取決于其帶來(lái)的實(shí)際價(jià)值。在泛型和迭代器的案例中,我們看到的是一種 “有條件的妥協(xié)”。
泛型和迭代器的加入標(biāo)志著 Go 的一個(gè)新階段,它不再只是一個(gè)適用于簡(jiǎn)單、高效系統(tǒng)的工具,而是向更廣泛的應(yīng)用場(chǎng)景進(jìn)發(fā)。
Go 的設(shè)計(jì)團(tuán)隊(duì)在這一過(guò)程中始終保持審慎態(tài)度,以確保每一個(gè)新特性都能夠在提升語(yǔ)言功能的同時(shí),盡量不違背其初衷。
總結(jié)
泛型和迭代器的引入無(wú)疑為 Go 增添了新的可能性,使其在處理復(fù)雜項(xiàng)目和數(shù)據(jù)密集型應(yīng)用時(shí)更加得心應(yīng)手。與此同時(shí),這些特性也提出了新的挑戰(zhàn),即如何在不影響開(kāi)發(fā)體驗(yàn)的前提下保持語(yǔ)言的簡(jiǎn)潔和一致性。
Kris 和 Ian 的討論反映了 Go 社區(qū)的一種共識(shí):Go 的發(fā)展需要與時(shí)俱進(jìn),但在增加新功能的同時(shí),必須始終銘記語(yǔ)言的核心設(shè)計(jì)理念。
未來(lái),我們可以期待 Go 語(yǔ)言在更多領(lǐng)域中展現(xiàn)其潛力,同時(shí)也繼續(xù)在簡(jiǎn)潔性與功能性之間找到理想的平衡點(diǎn)。