go 泛型初探
go1.17于几天前正式发布, 虽然 go的泛型还没正式发布,但 go 的泛型代码已经并入 master 分支, 所以我们可以在 go1.17版本中提前试用泛型。
下载 go1.17
如果你目前没有 go 的任何版本, 你只能去官网链接下载1.17版本, 如果已有了 go 的其它版本, 你可以通过以下方式下载使用go1.17:
go get golang.org/dl/go1.17
go1.17 download
go1.17 version
这样就1.17就下好了。
例子
接下来我们来看看2个使用泛型的例子。
例子1:
package main
import ("fmt")
func print[T any](s []T) {
for _, v := range s {
fmt.Println(v)
}
}
func main() {
print([]string{"Hello, ", "overstarry\n"})
print([]int64{1, 2, 3})
print([]float64{1, 2, 3})
}
go 使用[] 定义类型参数,与java、c++等的<>有很大不同,any关键字来表示任意类型约束。然后怎么运行呢? 简单的go run\build 是肯定不行的,要运行泛型代码,你需要在run\build 后加-G参数, 运行的命令是:
go1.17 run -gcflags=-G=3 main.go
可以看到,成功输出了相应的值。
接下来再来看个经典的例子, 由于go没有函数重载, 我们在写2数相加的时候,为了应对不同的类型情况,往往需要写很多不同的函数,现在来看看在泛型的情况下的add函数:
package main
import "fmt"
type Addable interface {
type int, int8, int16, int32, int64,
uint, uint8, uint16, uint32, uint64, uintptr,
float32, float64, complex64, complex128
}
func add[T Addable](a, b T) T {
return a + b
}
func main() {
fmt.Println(add(1, 2))
fmt.Println(add("foo", "bar"))
}
可以看到我们定义了一个 Addable 的接口, 接口定义了一系列类型,用来约束泛型函数的类型, 不在接口中的类型不能使用。
我们来运行看看吧,
可以看到,程序无法运行,提示string类型没有在接口约束中。我们加上 string 类型再试试看看,
这次程序顺利运行,输出了相应的值。
总结
本文主要是 go 泛型的简单初探,让我们静静等待明年2月份的 go1.18, 那时我们就能正式使用泛型了,目前的go1.17的泛型还不够完善,还存在一些问题, 如泛型函数不能导出(即首字母不能大写)。