Open wayou opened 2 years ago
Golang 1.18+ 中加入了泛型,果断升级后体验了一波。
考察数组求和的场景,为了对比,先来看不使用泛型时如何实现。
分别编写两个求和函数,对整形和浮点型进行求和。
func sumInt(a []int64) int64 { var sum int64 for _, v := range a { sum += v } return sum } func sumFloat(a []float64) float64 { var sum float64 for _, v := range a { sum += v } return sum }
然后在 main 函数中进行调用:
main
func main() { ints := []int64{1, 2, 3, 4, 5} floats := []float64{1.1, 2.2, 3.3, 4.4, 5.5} fmt.Printf("%v\n", sumInt(ints)) // 15 fmt.Printf("%v\n", sumFloat(floats)) // 16.5 }
上面没使用泛型的版本,针对不同类型的入参,需要编写单独的函数。泛型的引入便可解决该问题,使得函数可接收不同类型入参,在编译后进行类型替换。
以下是带泛型的求和函数:
func sum[T int64 | float64](a []T) T { var sum T for _, v := range a { sum += v } return sum }
其中函数名后面方括号中定义了类型 T,联合类型 int64 | float64 为一种入参约束(parameter constraint) 定义了函数可接收的参数类型,后续返回和函数体中可直接引用这里的 T 类型。
T
int64 | float64
然后在 main 函数中使用这个新定义的函数:
fmt.Printf("%v\n", sum[int64](ints)) // 指定类型的调用 fmt.Printf("%v\n", sum(ints)) // 省略类型的调用
使用时也是通过在函数名后面的方括号中指定具体的类型,当然也可以省略。当类型省略时,编译工具根据入参进行自动检测。所以并不是所有情况都能省略,即,函数本身不带入参的情况。
进一步可将上面的联合类型 int64 | float64 抽取到一个单独的类型中,方便复用,而不是每次都完整地书写一遍。
type Number interface { int64 | float64 }
使用上面新定义的类型约束更新我们的泛型函数:
- func sum[T int64 | float64](a []T) T { + func sum[T Number](a []T) T { var sum T for _, v := range a { sum += v } return sum }
函数的泛型入参并不局限于单个,可以是任意个。考察下面对一个 map 进行求和的情况:
func sumMap[K comparable, V int64 | float64](a map[K]V) V { var sum V for _, v := range a { sum += v } return sum }
上面一共声明了两个入参类型 K 及 V。其中 comparable 为 Golang 内置的类型,表示任意能进行对比(即运用 == 或 != 操作符)的类型都可作为合法输入,这里 K 作为 map 的键值。
K
V
comparable
==
!=
上述函数的调用:
numberMap := map[int64]float64{1: 1.1, 2: 2.2, 3: 3.3, 4: 4.4, 5: 5.5} fmt.Printf("%v\n", sumMap(numberMap)) // 16.5
Golang 泛型
Golang 1.18+ 中加入了泛型,果断升级后体验了一波。
考察数组求和的场景,为了对比,先来看不使用泛型时如何实现。
不使用泛型的数组求和
分别编写两个求和函数,对整形和浮点型进行求和。
然后在
main
函数中进行调用:加入泛型
上面没使用泛型的版本,针对不同类型的入参,需要编写单独的函数。泛型的引入便可解决该问题,使得函数可接收不同类型入参,在编译后进行类型替换。
以下是带泛型的求和函数:
其中函数名后面方括号中定义了类型
T
,联合类型int64 | float64
为一种入参约束(parameter constraint) 定义了函数可接收的参数类型,后续返回和函数体中可直接引用这里的T
类型。然后在
main
函数中使用这个新定义的函数:使用时也是通过在函数名后面的方括号中指定具体的类型,当然也可以省略。当类型省略时,编译工具根据入参进行自动检测。所以并不是所有情况都能省略,即,函数本身不带入参的情况。
类型约束
进一步可将上面的联合类型
int64 | float64
抽取到一个单独的类型中,方便复用,而不是每次都完整地书写一遍。使用上面新定义的类型约束更新我们的泛型函数:
多个入参类型
函数的泛型入参并不局限于单个,可以是任意个。考察下面对一个 map 进行求和的情况:
上面一共声明了两个入参类型
K
及V
。其中comparable
为 Golang 内置的类型,表示任意能进行对比(即运用==
或!=
操作符)的类型都可作为合法输入,这里K
作为 map 的键值。上述函数的调用:
相关资源