GoLang之泛型
注:本文已Go SDK v1.18进行讲解
1.实现非泛型函数
下面以 map 为例,先看非泛型如何处理,泛型又是如何处理。
假如有两个 map,分别是 map[string]int 和 map[string]float64,编写函数将 map 中的 value 值相加,返回结果。因为有两个类型,因此编写两个函数;
在 main 函数中初始化两个 map 并调用上面的函数
package main
import "fmt"
// SumInts adds together the values of m.
func SumInts(m map[string]int64) int64 {
var s int64
for _, v := range m {
s += v
}
return s
}
// SumFloats adds together the values of m.
func SumFloats(m map[string]float64) float64 {
var s float64
for _, v := range m {
s += v
}
return s
}
func main() {
// Initialize a map for the integer values
ints := map[string]int64{
"first": 34,
"second": 12,
}
// Initialize a map for the float values
floats := map[string]float64{
"first": 35.98,
"second": 26.99,
}
fmt.Printf("Non-Generic Sums: %v and %v\n",
SumInts(ints),
SumFloats(floats))
}
//Non-Generic Sums: 46 and 62.97
虽然得到了想要的结果,但 SumInts 和 SumFloats 的逻辑差不多。如果将来有其他类型,我们必须增加额外的函数,代码逻辑也类似。
有了泛型,只需要一个函数就可以实现以上两个函数的功能,而且可以方便扩展为支持其他相关类型,比如 map[iint]float64 等
2.实现泛型函数
[K comparable, V Number]是类型参数;
(m map[K]V)是普通函数参数
map[K]V 是一个 map,它的 key 类型是 K,value 类型是 V
我们把原本来函数声明里的 int64和float64的并集改造成了一个新的“类型限制接口”Number,声明了int64和float64的并集,当我们需要限制类型参数为int64或float64时,就可以使用Number这个类型限制来代替int64 | float64的写法。
int | float64 表示只允许是 int 或 float64,其他类型编译会报错,这是“类型约束”
我们定义了一个新的泛型函数,函数逻辑和之前定义过的泛型函数SumIntsOrFloats完全一样,只不过对于类型参数V,我们使用了Number来作为类型限制。和之前一样,我们把类型参数用于函数形参和函数返回类型
比如SumNumbers(ints),这个泛型函数调用里,我们忽略了类型实参(方括号[]里面的类型名称),Go编译器根据函数实参进行自动类型推导。
type Number interface {
int64 | float64
}
func SumNumbers[K comparable, V Number](m map[K]V) V {
var s V
for _, v := range m {
s += v
}
return s
}
func main() {
// Initialize a map for the integer values
ints := map[string]int64{
"first": 34,
"second": 12,
}
// Initialize a map for the float values
floats := map[string]float64{
"first": 35.98,
"second": 26.99,
}
fmt.Printf("Generic Sums with Constraint: %v and %v\n",
SumNumbers(ints),
SumNumbers(floats))
//输出:Generic Sums with Constraint: 46 and 62.97
}
3.comparable接口类型
comparable表示所有可比较类型,也就是说,K 可以是任意可比较类型
type comparable interface{ comparable }