Go1.24 新特性:泛型再查缺補漏,正式支持類型別名!
大家好,我是煎魚。
自從 Go1.18 支持泛型后,社區很多同學以為泛型會帶來非常巨大的改變。但實際上,還是比較尷尬的。因為泛型還在持續的迭代中,還處于發展期。
今天給大家分享的是 Go1.24 中給泛型加的新功能特性。一起來學習吧!
背景
泛型提案說:"類型別名(type alias)可以引用泛型,但類型別名不能有自己的參數。之所以有這一限制,是因為不清楚如何處理具有約束的類型參數的類型別名"。
對應的場景例子,一般聲明是如下代碼:
type A = P
但是在 Go1.24 以前,A 沒法包含泛型的類型參數。Go 官方在 go ref/spec#Alias_declarations[1] 中明確提到這種聲明方式是會報錯的:
type A[P any] = P // illegal: P is a type parameter
本次新的提案《spec: generics: permit type parameters on aliases[2]》專門針對這個問題給出了新的處理思路。
提案作者 @Matthew Dempsky 建議放寬這一限制,允許類型別名擁有自己的類型參數。
他認為有一種明確的方法可以處理帶有約束類型參數的類型別名:“類型別名的使用需要滿足約束,而在底層類型表達式中,這些參數可以用來實例化它們所滿足的其他泛型。”
Go1.24:泛型支持類型別名
終于,經過一番 issues 討論和整合(花了 4 年!!!)在即將 2 月份發布 Go1.24 將會支持類型別名。
具體的 Go1.24 的使用例子如下:
// 定義一個通用切片類型
type GenericSlice[T any] = []T
// 示例:自定義結構體切片
type Fish struct {
Name string
IsGrilled bool
Ingredients []string
}
func main() {
// 示例:字符串切片
words := GenericSlice[string]{"Go", "Rocks"}
fmt.Println("Words:", words)
fishes := GenericSlice[Fish]{
{Name: "Salmon", IsGrilled: true, Ingredients: []string{"Salt", "Lemon", "Garlic"}},
{Name: "Tuna", IsGrilled: false, Ingredients: []string{"Soy Sauce", "Wasabi"}},
}
fmt.Println("Grilled Fish Menu:", fishes)
}
輸出結果:
Words: [Go Rocks]
Grilled Fish Menu: [{Salmon true [Salt Lemon Garlic]} {Tuna false [Soy Sauce Wasabi]}]
如果你是 Go1.23 的版本,將會報:./prog.go:6:6: generic type alias requires GOEXPERIMENT=aliastypeparams 這個錯誤。
是因為該特性在 Go1.23 起作為實驗特性加入。在 Go1.24 計劃正式轉正。
總結
自 Go1.18 泛型正式加入 Go 這門編程語言來,感覺一直還在修修補補的路上。這次支持類型別名,也花了將近 4 年。
雖然整體還能用,但是還是磕磕碰碰。希望越來越好了。
參考資料
[1]go ref/spec#Alias_declarations: https://tip.golang.org/ref/spec#Alias_declarations
[2]spec: generics: permit type parameters on aliases: https://github.com/golang/go/issues/46477