泛型

问题解决

一个计算sum的函数

func sum(slice []int) int {	var res int	for _, value := range slice {		res += value	}	return res}

​ 如果需要提供对int,float64,string三种数据类型的求sum函数,那么不使用泛型的情况下就需要单独写三个函数,此时就需要使用泛型这种概念,来避免重复代码出现

// 这里中括号中括起来的就是泛型的定义,将这三种数据类型定义为T泛型,同时使用T泛型来定义入参和返回值的数据类型func Sum[T int | float64 | string](slice []T) T {	var res T	for _, value := range slice {		res += value	}	return res}// 这样在调用函数的时候,只需要知道具体T泛型对应的是哪种数据类型,就可以确定入参和返回值的数据类型了func main() {	slice01 := []int{1, 2, 3}	fmt.Printf("%d\n", Sum(slice01)) // 6	slice02 := []float64{1.2, 2.2, 3.2}	fmt.Printf("%.2f\n", Sum(slice02))  // 6.60	slice03 := []string{"Hello", " ", "world!"}	fmt.Printf("%s\n", Sum(slice03)) // Hello world!}

泛型的使用

  1. 在函数传参中使用泛型

​ 同上一个例子相同,在函数声明中定义泛型,然后将他利用于入参,返回值,以及函数的内部定义

func Demo01[T int | string](input T) {	fmt.Println(reflect.TypeOf(input))}func main() {    // 通过传参来判断泛型T具体的数据类型    // T:string    Demo01("我是string类型") // string    // T:int    Demo01(123) // int}
  1. 泛型结构体

​ 同样,泛型也适用于结构体,在结构体声明时定义泛型,既可以在结构体内部使用泛型来声明值的类型

// 使用泛型T来让生产日期的数据类型多样化,可以是int也可以是stringtype robots[T int | string] struct {	name             string	yearOfProduction T}func Demo03() {    // 使用带有泛型的结构体实例化对象的时候,要确定泛型T的具体类型    // T:string	myRobot01 := robots[string]{"robot01", "2023"}    // T:int	myRobot02 := robots[int]{"robot02", 2023}	fmt.Printf("%T : %T\n", myRobot01.name, myRobot01.yearOfProduction) // string : string	fmt.Println(myRobot01.name, " : ", myRobot01.yearOfProduction) // robot01  :  2023	fmt.Printf("%T : %T\n", myRobot02.name, myRobot02.yearOfProduction) // string : int	fmt.Println(myRobot02.name, " : ", myRobot02.yearOfProduction) // robot02  :  2023}
  1. 给泛型添加方法

// 先声明带有泛型的切片slice[]type Slice[T int | string | float64] []T// 然后给这个切片添加方法func (mySlice Slice[T]) Demo04() T {	var res T	for _, t := range mySlice {		res += t	}	return res}func main() {    // 再使用切片实例化对象时同样需要先确定泛型T的具体类型	var slice01 Slice[int] = []int{1, 2, 3}    // 直接使用里面的方法	fmt.Printf("%d\n", slice01.Demo04())	var slice02 Slice[float64] = []float64{1.2, 2.2, 3.2}	fmt.Printf("%.2f\n", slice02.Demo04())	var slice03 Slice[string] = []string{"Hello", " ", "world!"}	fmt.Printf("%s\n", slice03.Demo04())}
  1. 自定义泛型类型

​ 如果类型太多了怎么办呢?这时候我们就可以自定义泛型类型

// 声明方式类似接口type MyInt interface{    int | int8 | int16 | int32 | int64}// T的类型为声明的MyIntfunc GetMax[T MyInt](a,b T) T {    if a > b {        return a    }    return b}

特殊的泛型

go里内置了两个泛型类型:any和comparable

泛型类型作用
any表示go里面所有的内置基本类型,等价于interface{}
comparable表示go里面所有内置的可以进行比较的类型