Go的泛型
一、类型参数
使用类型参数,Go函数能够被写出来作用于多种类型。一个函数的类型参数出现在括号之前和函数参数之前。
func Index[T comparable](s []T, x T) int
这个声明意味着s
是一个任意类型T
的的切片,它完全满足内置约束comparable
。x
是某一个值。
comparable
是一个有用的约束,让其在类型的值上使用==
和!=
操作符成为可能。在这个例子中,我们使用它让值和切片中所有元素对比,直到匹配。这个Index
函数对于任何支持对比的类型,都起作用。
package main
import "fmt"
func Index[T comparable](s []T, x T) int {
for i, v := range s {
// v 和 x 都是T类型,它们有用comparable约束,因为能在这里使用 ==
if v == x {
return i
}
}
return -1
}
func main() {
// Index 能作用在int类型的切片上
si := []int{10, 20, 15, -10}
fmt.Println(Index(si, 15))
// Index 也能作用在string类型的切片行
ss := []string{"foo", "bar", "baz"}
fmt.Println(Index(ss, "Hello"))
}
二、泛型类型
除了泛型函数,Go也支持泛型类型。一个类型能够使用一个类型参数进行参数化。这是非常有用的对于实现泛型的数据结构。
这个例子演示了一个简单的类型声明,一个单链表,可以支持任何数据。
作为联系,添加一些功能为这个链表,变成一个list实现。
package main
import "fmt"
// List 代表一个单链表,可以持有任何数据
type List[T any] struct {
next *List[T]
val T
}
func (l *List[T]) Push(t T) {
if l.next == nil {
l.next = &List[T]{val: t}
} else {
l.next.Push(t)
}
}
func (l *List[T]) GetALL() []T {
res := make([]T, 0)
l2 := l
for l2 != nil {
res = append(res, l2.val)
l2 = l2.next
}
return res
}
func main() {
l := List[int]{val: -1}
oneL := []int{2, 3, 4, 5, 6, 7, 8, 9}
for _, v := range oneL {
l.Push(v)
}
fmt.Println(l.GetALL())
// l := List.New[int]{"next": nil, "var": 23}
// l.add(2)
// fmt.Println()
}