泛型
- 对于强类型语言,在编写代码时不事先指定类型,在实例化的时候作为参数指明类型
参考: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应该是同一类型,但是调用的时候我可以传入不同类型,为了不出问题,还得在函数里面做类型判断
- 泛型在编译时有类型校验
- 泛型相较于接口的优点
- 更安全:编译早期发现错误
- 更高效:静态类型
- interface在类型上太随意
代码示例
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"})
}