大家好,我是煎鱼。
自从 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