Go-知识泛型
- 1. 认识泛型
- 1.1 不使用泛型
- 1.2 使用泛型
- 2. 泛型的特点
- 2.1 函数泛化
- 2.2 类型泛化
- 3. 类型约束
- 3.1 类型集合
- 3.2 interface 类型集合
- 3.2.1 内置interface类型集合
- 3.2.2 自定义interface类型集合
- 3.2.2.1 任意类型元素
- 3.2.2.2 近似类型元素
- 3.2.2.3 联合类型元素
- 3.2.3 interface类型集合运算
- 3.2.4 基于操作的类型集合
- 4. 小例子
- 4.1 map.Keys 获取map的全部key
- 4.2 Set
- 4.3 排序 Sort
- 5. 总结
泛型是程序设计语言的一种风格或范式,允许程序员在编写代码时使用一些以后才指定的类型,在实例化时作为参数指明这些类型。
Java,C++等多种编程语言都支持泛型,Go语言从1.18版本起也开始支持泛型。
1. 认识泛型
1.1 不使用泛型
实现两个函数对map的value值进行累加,一个是int64类型的值,一个是float64类型的值
func SumInt64(m map[string]int64) int64 {var sum int64for _, v := range m {sum += v}return sum
}func SumFloat64(m map[string]float64) float64 {var sum float64for _, v := range m {sum += v}return sum
}
接着使用两个函数
func TestSum(t *testing.T) {ints := map[string]int64{"one": 234,"two": 6755,"three": 78675,}floats := map[string]float64{"one": 123.456,"two": 7865.9658,"three": 87906.865,}t.Logf("sum ints : %v , floats : %v", SumInt64(ints), SumFloat64(floats))
}
执行如下:
实现同样的功能,就因为处理的数据类型不一样,就需要为每种类型编写类似的重复代码。
1.2 使用泛型
泛型函数,就是吧函数的参数和返回值“泛化”,使逻辑通用。 通用并不是对所有类型都使用,所以在声明泛型函数时,需要声明适用的“参数类型”(类型约束).
func SumValue[K comparable, V int64 | float64](m map[K]V) V {var sum Vfor _, v := range m {sum += v}return sum
}
SumValue泛型函数通过[K comparable, V int64|fload64]
声明了两个类型参数K,V,供函数参数和返回值使用。
类型参数K的类型必须为comparable类型,因为被用作map的key值,在Go语言中map的key值必须是可比较的类型。
类型参数V的类型可以是int64或float64,在声明时使用|
组合支持的类型。
普通参数m 表示一个泛化的map,相应的返回值也是一个泛化的类型。
使用:
func TestSumValue(t *testing.T) {ints := map[string]int64{"one": 234,"two": 6755,"three": 78675,}floats := map[string]float64{"one": 123.456,"two": 7865.9658,"three": 87906.865,}t.Logf("sum ints : %v , floats : %v", SumValue(ints), SumValue[string, float64](floats))
}
执行结果
在调用泛型函数的地方,编译器会将泛型函数实例化,即使用真实的类型来替换类型参数,在调用时有两种方式:
- 隐式调用: 调用泛型函数时使用缺省类型参数,让编译器根据实际的参数进行推导。(SumValue(ints))
- 显示调用: 调用泛型函数时显式的指明类型参数。(SumValuestring, float64)
需要注意的是,编译器之所以能够推导出参数类型是因为函数存在入参,编译器通过传入的变量和函数的参数声明可以推导出参数类型,但对于没有函数参数的泛型函数来说,编译器
无法进行推导,也就无法实例化泛型函数,此时必须显式地调用并指定类型参数。
比如:
就无法推导出来返回值的类型了
而且显式调用,必须全部指定,不能指定部分类型
2. 泛型的特点
泛型的英文表述为generic,即一般化,泛化,具体来讲就是函数和类型的泛化。在泛型被引入之前一个函数所能接收的参数类型及
所能处理的数据类型是确定的,但泛型