go 语言泛型

GO 泛型介绍

Go 1.18 版本增加了对泛型的支持。泛型是自Go语言开源以来对Go做出的一次最大的变更。

泛型在Go语言中增加了三个新的重要内容:

函数和类型新增对**类型形参(type parameters)的支持。
将接口类型定义为类型集合,包括没有方法的接口类型。
支持类型推导,大多数情况下,调用泛型函数时可省略类型实参(type arguments)。

类型形参 (Type Parameters)

现在,函数和类型被允许拥有类型形参(Type Parameters)。一个类型形参列表看起来和普通的函数形参列表一样,只是它使用的是方括号而不是小括号。语法 :

func 函数名称 [T 类型形参 ](参数 T){}
func 函数名称 [T String|int|... 类型 ](参数 T){}

一个示例( P 函数可以打印多种类型数据 ):

package main
import "fmt"
func P[T string | int](data T) {
	fmt.Printf("data: %T\n", data)
	println(data)
}
func main() {
	P[string]("a")
	P[int](11)
	// 不支持的类型
	// P[float32](1.1)
}

为什么使用泛型

所谓泛型,简单地理解就是广泛的类型。

从函数的参数角度讲,我们在定义一个函数参数时会规范其具体类型,如果参数类型不固定,之前使用 any 和断言来解决(效率一般),有了泛型我们就可以实现参数的动态类化。相对于断言、反射,泛型具备类型安全、高效等优点。

使用 type 定义泛型切片示例

// 定义一个泛型切片类型
type MySlice[T int | string] []T

func main() {
	s1 := MySlice[string]{"a", "b", "c"}
	fmt.Printf("s1: %v\n", s1)
	s2 := MySlice[int]{1, 2, 3}
	fmt.Printf("s1: %v\n", s2)
}

泛型 Map 示例

package main

import "fmt"

// 定义一个泛型 map
type MyMap[KEY int | string, VALUE float32 | float64] map[KEY]VALUE

func main() {
	var m1 MyMap[string, float64] = map[string]float64{"go": 9.9, "java": 9.0}
	fmt.Printf("m1: %v\n", m1)
}