第16节 Go genericity(泛型)

❤️💕💕Go语言高级篇章,在此之前建议您先了解基础和进阶篇。Myblog:http://nsddd.topopen in new window

Go语言基础篇open in new window

Go语言100篇进阶open in new window


[TOC]

先决条件

提示

随着 2022 年 3 月 15 日 go 1.18 正式发布,新版本除了对性能的提升之外,还引入了很多新功能,其中就有 go 期盼已久的功能泛型(Generics),同时还引入的多模块工作区(Workspaces)和模糊测试(Fuzzing)。

  • **安装 Go 1.18 或更高版本。**有关安装说明,请参阅安装 Goopen in new window.
  • **用于编辑代码的工具。**您拥有的任何文本编辑器都可以正常工作。
  • **命令终端。**Go 在 Linux 和 Mac 上的任何终端以及 Windows 中的 PowerShell 或 cmd 上运行良好。

上手–解决相加问题

💡简单的一个案例如下:

package main

import "fmt"

type MySlice[T int | float64 | string] []T

func (s MySlice[T]) Sum() T {
	var sum T
	for _, v := range s {
		sum += v
	}
	return sum
}

func main() {
	s := MySlice[int]{1, 2, 3}
	fmt.Println(s.Sum())

	v := MySlice[float64]{1.1, 2.2, 3.3}
	fmt.Println(v.Sum())

	u := MySlice[string]{"hello", "world"}
	fmt.Println(u.Sum())
}

🚀 编译结果如下:

[Running] go run "d:\文档\最近的\awesome-golang\docs\code\go-super\71-main.go"
6
6.6
helloworld

📜 对上面的解释

泛型函数,该函数可以接收包含整数或浮点值的映射,从而有效地将刚刚编写的两个函数替换为单个函数。

若要支持任一类型的值,该单个函数将需要一种方法来声明它支持的类型。另一方面,调用代码需要一种方法来指定它是使用整数还是浮点映射进行调用。

类型参数必须支持泛型代码对其执行的所有操作。例如,如果函数的代码要尝试对其约束包含数值类型的类型参数执行string操作(如索引),则代码将无法编译。

类比两个数也是可以的~

💡简单的一个案例如下:
package main

import "fmt"

type MySlice[T int | float64 | string] []T

func (s MySlice[T]) Sum() T {
	var sum T
	for _, v := range s {
		sum += v
	}
	return sum
}

//泛型(genericity)函数
func Add[T int | float64 | string](a, b T) T {
	return a + b
}

func main() {
	s := MySlice[int]{1, 2, 3}
	fmt.Println(s.Sum())

	v := MySlice[float64]{1.1, 2.2, 3.3}
	fmt.Println(v.Sum())

	u := MySlice[string]{"hello", "world"}
	fmt.Println(u.Sum())

	fmt.Println(Add(1, 2))
	fmt.Println(Add(1.1, 2.2))
	fmt.Println(Add("hello", "world"))
}

🚀 编译结果如下:

[Running] go run "d:\文档\最近的\awesome-golang\docs\code\go-super\71-main.go"
6
6.6
helloworld
3
3.3000000000000003
helloworld

我们可以同过一个方法去适配很多个方法。

⚠️需要注意

func Add[T int | float64 | string](a, b T) T {
	return a + b
}

注意我们的泛型(genericity)类型如果指定 any ,那么是不会成功的(interface{}只能返回一个值

func Add[T any](a, b T) T {
	return a + b
}

我们看一下 any 源码:

type any = interface{}
  • any :表示 Go语言 所有内置的基本类型
  • comparable:表示在Go语言里面所有内置的可比较类型

🔽 我们也可以自定义泛型(genericity)类型

自定义泛型(genericity)约束

如果类型太多了怎么办,我们针对Add[T int | float64 | string](a, b T) T 而言,我们使用 interface定义:

/*
自定义泛型(genericity)类型
*/

package main

import "fmt"

type MyInt interface {
	int | int64 | int32 | int16 | int8
}

func GetMaxNum[T MyInt](a, b T) T {
	if a > b {
		return a
	}
	return b
}

func main() {
	fmt.Println(GetMaxNum(1, 2))
}

🚀 编译结果如下:2

END 链接