GO——泛型

时间:2024-06-08 12:10:26

泛型

  • 对于强类型语言,在编写代码时不事先指定类型,在实例化的时候作为参数指明类型

参考:https://www.liwenzhou.com/posts/Go/generics/

什么时候使用泛型?

  • 方法中的代码实现与类型T无关
  • 参考:https://juejin.cn/post/7089321525781725214
  • interface与泛型
    • 操作没有方法的类型,interface类型不适用
    • 每个类型的操作逻辑不一样,泛型不适用

泛型与继承的区别

  • 参考:https://www.cnblogs.com/wdmx/p/9922371.html
  • 泛型是指广泛的类型,是横向的
    • 用在与类型无关的函数中
      • 比如函数将相同的算法作用到不同的类型上,类型在使用的时候再确定
  • 继承是垂直的
    • 不同的类型之间有了共同的方法,会抽象出来一个父类。
    • 多态,相同的方法,不同的实现
  • 我的理解
    • 继承:不同的对象,有相同的方法名,但是实现不同,属于同一个类
    • 泛型:不同的对象,作用在他们身上的逻辑相同,与他们的类型无关,可用泛型。

方法与函数

  • 参考:https://juejin.cn/post/6894899185221697550
  • 方法是包含了接受者的函数
    • 方法属于类
    • 函数就是代码集合

泛型与interface?

  • interface可以认为是基类,走继承的那条道
  • interface也可以实现泛型
  • 参考:https://golang3.eddycjy.com/posts/generics-history/
    • interface在类型上太随意
      • 比如add(a,b),a,b应该是同一类型,但是调用的时候我可以传入不同类型,为了不出问题,还得在函数里面做类型判断
    • 泛型在编译时有类型校验
    • 泛型相较于接口的优点
      • 更安全:编译早期发现错误
      • 更高效:静态类型

代码示例

package main

import "log"

//继承

type StructBase interface {
	GetName() string
}

type StructA struct {
	Name    string
	ColumnA string
}

func (a StructA) GetName() string {
	return a.Name
}

type StructB struct {
	Name    string
	ColumnB string
}

func (b StructB) GetName() string {
	return b.Name
}

func PrintName(s StructBase) {
	log.Println(s.GetName())
}

// 泛型
func reverse(arr []int) []int {
	res := make([]int, len(arr))
	for i := len(arr) - 1; i >= 0; i-- {
		res[len(arr)-1-i] = arr[i]
	}
	return res
}

func reverseGeneric[T any](arr []T) []T {
	res := make([]T, len(arr))
	for i := len(arr) - 1; i >= 0; i-- {
		res[len(arr)-1-i] = arr[i]
	}
	return res
}

func main() {
	//泛型测试
	arr := []int{1, 2, 3, 4, 5}
	log.Println(reverse(arr))
	log.Println(reverseGeneric(arr))
	log.Println(reverseGeneric(arr))
	log.Println(reverseGeneric([]int{1, 2, 3, 4, 5}))

	arr2 := []string{"a", "b", "c", "d", "e"}
	log.Println(reverseGeneric(arr2))

	//继承测试
	log.Println("=========================================")
	PrintName(StructA{Name: "structA", ColumnA: "columnA"})
	PrintName(StructB{Name: "structB", ColumnB: "columnB"})

}