Golang泛型的使用方法详解

作者:梦想画家

这篇文章主要介绍了Golang中泛型的使用,Go和Python语言不同,处理不同数据类型非常严格。如Python可以定义函数带两个数值类型并返回较大的数值,但可以不严格指定参数类型为float或integer

Go 和Python语言不同,处理不同数据类型非常严格。如Python可以定义函数带两个数值类型并返回较大的数值,但可以不严格指定参数类型为float或integer。同样功能go1.18之前版本需要定义两个函数分别处理对应类型,通过泛型可以实现上面描述功能,无需为每种类型重复定义函数。

本文通过示例学习Go泛型,包括三个部分:非泛型函数,泛型函数,泛型类型约束。

泛型的作用

我们知道Go一些函数(如fmt.Println)使用空interface支持多种数据类型,但需要开发者写大量代码实现很多函数或方法支持多种自定义类型不是最佳选项,于是泛型登场,提供新的解决方案,无需使用接口和反射支持多种数据类型。

下面通过示例来说明:

package main
import (
    "fmt"
func Print[T any](s []T) {
    for _, v := range s {
        fmt.Print(v, " ")
    fmt.Println()
func main() {
    Ints := []int{1, 2, 3}
    Strings := []string{"One", "Two", "Three"}
    Print(Ints)
    Print(Strings)

上面代码种Print()函数使用泛型,通过在函数名称和参数之间增加[T any]指定泛型变量, 既然T 为any类型,函数可传入任何数据类型slice。当然Print函数不能处理slice之外的输入,这是因为函数实现决定的。通过泛型函数可以避免针对每种数据类型编写函数,这种通用的思想就是泛型。

非泛型函数

我们实现两个函数,返回数值类型数组元素的和。我们至少创建两个函数,一个针对float64类型,另一个为int64,因此工作量翻倍。

package main
import "fmt"
func main() {
   f := []float64{1.0, 2.0, 3.0, 4.0, 5.0}
   i := []int64{1, 2, 3, 4, 5}
   s1 := SumOfFloat(f)
   s2 := SumOfIntegers(i)
   fmt.Println("Sum for float64 :", s1)
   fmt.Println("Sum for int64 :", s2)
func SumOfFloat(nums []float64) float64 {
   var sum float64
   for _, num := range nums {
       sum += num
   return sum
func SumOfIntegers(nums []int64) int64 {
   var sum int64
   for _, num := range nums {
       sum += num
   return sum

运行输出结果:

$ go run main.go
Sum for float64 : 15
Sum for int64 : 15

上面代码针对两种类型定义了两个函数,返回各自参数对应类型数组元素之和。下面通过泛型合并两个函数为一个,节约时间和精力。

本节实现单个函数,参数仍然是数组,但类型可以为float64或int64,并返回数组元素之和,从而可以代替上面两个函数。

为了能够定义函数接收float64和int64两种类型,新的泛型函数需要声明接收的类型,即调用代码需要判断类型是否为float64或int64。为此,新的函数签名需要有点变化,除了普通的参数外,还需要声明类型参数,从而转换函数为泛型函数支持不同类型。

每个形参都有一个类型约束,它指定调用代码可用于形参允许的实参类型。在编译时这些参数表示的类型就是调用代码支持的类型。当然泛型函数的实现逻辑需要支持形参声明的所有类型。举例,泛型函数支持字符串和数值参数,函数实现逻辑需要对参数进行索引,显然数值无法索引将引起编译错误。

泛型函数语法:

func genericFunction[T any](s []T) []T{

解释如下:

上面语法种在名称和参数之间的[]用于指定形式参数类型,可以是一组类型或一个约束接口。T 参数类型,用于定义形式参数和返回值类型。

函数内部也可以访问参数,any 是一个interfaceT必须实现该接口。Go1.18版本引入any,底层引用空接口,即interface{}。 下面举例说明:

package main
import "fmt"
func main() {
   f := []float64{1.0, 2.0, 3.0, 4.0, 5.0}
   i := []int64{1, 2, 3, 4, 5}
   s1 := genericSum(f)
   s2 := genericSum(i)
   fmt.Println("Sum for float64 :", s1)
   fmt.Println("Sum for int64 :", s2)
func genericSum[N int64 | float64](nums []N) N {
   var sum N
   for _, num := range nums {
       sum += num
   return sum

输出结果:

$ go run main.go
Sum for float64 : 15
Sum for int64 : 15

上面示例中演示定义泛型函数genericSum。参数类型在[]中声明的泛型类型。N声明在形参和返回值中使用,N是新的类型,被限定了两种类型float64 和 int64的联合类型。

在函数体类,首先声明N类型变量,然后遍历数组计算综合并返回。

假设泛型函数支持很多种类型,比如:int, int8 , int26, int32, int64, float32, float64。这样函数签名变得非常冗长难看,我们可以定义一个类型包括上述类型,本质上就是把联合类型迁移至函数声明外面。

package main
import "fmt"
type Number interface {
   int64 | float64
func main() {
   f := []float64{1.0, 2.0, 3.0, 4.0, 5.0}
   i := []int64{1, 2, 3, 4, 5}
   s1 := genericSum(f)
   s2 := genericSum(i)
   fmt.Println("Sum for float64 :", s1)
   fmt.Println("Sum for int64 :", s2)
func genericSum[N Number](nums []N) N {
   var sum N
   for _, num := range nums {
       sum += num
   return sum

本文是关于Go泛型的,因为泛型是Golang的新成员。通过对比带泛型和不带泛型的函数,泛型可以很明显地节省时间和精力。泛型不是接口的替代品,两者被设计为一起工作,避免重复代码,让Go类型更安全、代码更整洁。

到此这篇关于Golang泛型的使用方法详解的文章就介绍到这了,更多相关Golang泛型内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:
  • GO语言函数(func)的声明与使用详解
    GO语言函数(func)的声明与使用详解
    2022-12-12
  • Golang 中的 条件变量(sync.Cond)详解
    Golang 中的 条件变量(sync.Cond)详解
    2022-12-12
  • Go语言学习之将mp4通过rtmp推送流媒体服务的实现方法
    Go语言学习之将mp4通过rtmp推送流媒体服务的实现方法
    2022-12-12
  • 详解Go语言如何进行Http调用
    详解Go语言如何进行Http调用
    2022-12-12
  • Go语言基础学习之数组的使用详解
    Go语言基础学习之数组的使用详解
    2022-12-12
  • Go语言题解LeetCode268丢失的数字示例详解
    Go语言题解LeetCode268丢失的数字示例详解
    2022-12-12
  • Go语言题解LeetCode455分发饼干示例详解
    Go语言题解LeetCode455分发饼干示例详解
    2022-12-12
  • Go语言题解LeetCode463岛屿的周长示例详解
    Go语言题解LeetCode463岛屿的周长示例详解
    2022-12-12
  • 美国设下计谋,用娘炮文化重塑日本,已影响至中国
    美国设下计谋,用娘炮文化重塑日本,已影响至中国
    2021-11-19
  • 时空伴随者是什么意思?时空伴随者介绍
    时空伴随者是什么意思?时空伴随者介绍
    2021-11-09
  • 工信部称网盘企业免费用户最低速率应满足基本下载需求,天翼云盘回应:坚决支持,始终
    工信部称网盘企业免费用户最低速率应满足基本下载需求,天翼云盘回应:坚决支持,始终
    2021-11-05
  • 2022年放假安排出炉:五一连休5天 2022年所有节日一览表
    2022年放假安排出炉:五一连休5天 2022年所有节日一览表
    2021-10-26
  • 电脑版 - 返回首页

    2006-2023 脚本之家 JB51.Net , All Rights Reserved.
    苏ICP备14036222号