2022年3月15日,争议非常大但同时也备受期待的泛型终于伴随着Go1.18发布了。
平时对于版本更新都是漠不关心的,只是近几个月关于泛型的讨论呼声越来越高,于是也来学习一下。
在开始之前,请先将你的Go升级到1.18及以上的版本
1.假设有一个求和的函数
我们先在当前目录运行 go mod init 命令,为其提供新代码的模块路径
go mod init test
go: creating new go.mod: module test
go: to add module requirements and sums:
go mod tidy
在当前目录新建一个 main.go 文件
那么在早期的版本你可能会这样写
func Add(num map[string]int64) int64 {
var ret int64
for _, v := range num {
ret += v
}
return ret
}
在这段代码中:
我们声明了一个 map,从中循环取值累加并返回总和
那么调用的语句如下
func main() {
InitNum := map[string]int64{
"First": 10,
"Second": 20,
"Third":30,
}
fmt.Printf("Sum of all number is:%v",Add(InitNum))
}
在终端中输入 go run main.go,运行代码
$ go run main.go
Sum of all number is:60
2.如果我们想要对不同类型的参数求和呢?
你可能会想到:那我把参数的类型修改下,多搞几个函数一一对应就好了
例如下面这样:
func Add1(num map[string]int64) int64 {
var ret int64
for _, v := range num {
ret += v
}
return ret
}
func Add2(num map[string]float64) float64 {
var ret float64
for _, v := range num {
ret += v
}
return ret
}
但是这样修改就有个问题:用起来太麻烦了,每想要一个新类型就要新生成一个对应类型的函数
泛型就能够很好解决上述问题
3.添加泛型来处理多种类型
还是上面那个求和的案例,如果使用泛型,我们可以这么写:
func SumIntOrFloat[K comparable, V int64 | float64](m map[K]V) V {
var s V
for _, v := range m {
s += v
}
return s
}
- []中声明了两个类型参数 K 和 V,m 类型为 map[K]V。该函数返回一个类型为 V 的值。
- comparable 是 golang 新引入的预定义标识符,它允许任何类型的值可以用作比较运算符 == 和 !=
- int64 和 float64。使用 | 指定两种类型的联合,这意味着此约束允许任何一种类型。编译器将允许任一类型作为调用代码中的参数。
那么我们就可以很愉快的用不同类型的参数去调用这个求和函数
func main() {
IntNum := map[string]int64{
"First": 10,
"Second": 20,
"Third":30,
}
FloatNum := map[string]float64{
"First": 10,
"Second": 20,
"Third":30,
}
fmt.Printf("Sum of all int number is:%v \n", SumIntOrFloat(IntNum))
fmt.Printf("Sum of all float number is:%v ", SumIntOrFloat(FloatNum))
}
在终端中执行,输出结果为:
$ go run .
Sum of all int number is:60
Sum of all float number is:60