Go语言泛型函数的用法(附带实例)
泛型全称为泛型程序设计(Generic Programming),它是程序设计语言的一种风格或范式。
泛型允许程序员在强类型编程语言中实例化某个对象的时候才指明参数的数据类型。不同编程语言的编译器(解释器)、运行环境对泛型的支持均不一样。
Go 语言在定义函数方法的时候,必须对参数和返回值设置数据类型,调用过程中必须按照定义的数据类型设置参数值和返回值,如果传递数据的数据类型与定义的数据类型不相符,则提示异常,如下图所示:

图 1 数据类型异常
若想要函数的参数和返回值不受数据类型限制,可以将参数和返回值设置为空接口,空接口能给使用者传递任意数据类型的数据,但如果函数只允许传递部分数据类型的数据,则需要由泛型实现。
简单来说,在函数中使用泛型,只要在函数名后面和参数前面使用中括号“[]”,分别对参数和返回值设置一个或多个数据类型即可,详细示例如下:
上述代码主要分为两部分:泛型函数的定义与调用。
函数 sum() 设置泛型 K 和 V,泛型 K 为字符串类型,泛型 V 为整型或浮点型。函数参数 m 为集合类型,集合的键的数据类型为泛型 K(即字符串类型),值的数据类型为泛型 V(即整型或浮点型)。函数返回值为泛型 V,即返回值数据类型为整型或浮点型。
调用函数 sum() 的时候,必须使用中括号
综上所述,泛型函数是对函数参数或返回值设置多个数据类型,比普通函数更灵活地设置参数类型和返回值类型,但比不上空接口参数的开放自由。
既然开放性比不上空接口,为什么还要引入泛型?因为空接口参数不受数据类型的限制,如果调用过程中,函数传入参数是无法处理的数据类型,则容易引起异常。
使用泛型可以保证参数(返回值)类型的多样性,也能保证调用过程中不会传入非法参数。正如我们常听的一句话:所有的自由都是在有限制的前提下才叫自由。
泛型允许程序员在强类型编程语言中实例化某个对象的时候才指明参数的数据类型。不同编程语言的编译器(解释器)、运行环境对泛型的支持均不一样。
Go 语言在定义函数方法的时候,必须对参数和返回值设置数据类型,调用过程中必须按照定义的数据类型设置参数值和返回值,如果传递数据的数据类型与定义的数据类型不相符,则提示异常,如下图所示:

图 1 数据类型异常
若想要函数的参数和返回值不受数据类型限制,可以将参数和返回值设置为空接口,空接口能给使用者传递任意数据类型的数据,但如果函数只允许传递部分数据类型的数据,则需要由泛型实现。
Go语言泛型函数
在函数中使用泛型,必须在函数名后面和参数前面设置泛型,其语法格式如下:func name[p, r](parameter p) r { parameter return returnType }函数定义说明如下:
- func 是 Go 语言的关键字,用于定义函数和方法。
- name 是函数名,可自行命名。
- parameter 是函数参数。
- p 是为参数 parameter 设置数据类型,多个数据类型之间以“|”隔开,如 int | string。
- r 是为返回值设置数据类型,多个数据类型之间以“|”隔开,如 int | string。
简单来说,在函数中使用泛型,只要在函数名后面和参数前面使用中括号“[]”,分别对参数和返回值设置一个或多个数据类型即可,详细示例如下:
package main import "fmt" // 定义泛型函数 func sum[K string, V int | float64](m map[K]V) V { var s V for _, v := range m { s += v } return s } func main() { // 定义变量 myints := map[string]int{ "first": 34, "second": 12, } // 定义变量 myfloats := map[string]float64{ "first": 35.98, "second": 26.99, } // 输出计算结果 fmt.Printf("泛型函数的int:%v\n", sum[string, int](myints)) fmt.Printf("泛型函数的float64:%v\n",sum[string,float64](myfloats)) }运行上述代码,结果为:
泛型函数的int:46
泛型函数的float64:62.97
上述代码主要分为两部分:泛型函数的定义与调用。
函数 sum() 设置泛型 K 和 V,泛型 K 为字符串类型,泛型 V 为整型或浮点型。函数参数 m 为集合类型,集合的键的数据类型为泛型 K(即字符串类型),值的数据类型为泛型 V(即整型或浮点型)。函数返回值为泛型 V,即返回值数据类型为整型或浮点型。
调用函数 sum() 的时候,必须使用中括号
[ ]
为泛型 K 和 V 设置具体的数据类型,然后再传递相应数据执行调用过程。综上所述,泛型函数是对函数参数或返回值设置多个数据类型,比普通函数更灵活地设置参数类型和返回值类型,但比不上空接口参数的开放自由。
既然开放性比不上空接口,为什么还要引入泛型?因为空接口参数不受数据类型的限制,如果调用过程中,函数传入参数是无法处理的数据类型,则容易引起异常。
使用泛型可以保证参数(返回值)类型的多样性,也能保证调用过程中不会传入非法参数。正如我们常听的一句话:所有的自由都是在有限制的前提下才叫自由。