泛型函数
通过 类型参数 ,Go 语言能够编写可以处理多种类型的函数。函数的类型参数位于参数列表前,以中括号括起来:
1
|
func Index[T comparable](s []T, x T) int
|
这个申明表示:s 是任意类型 T 的切片,x 是类型 T ,而 T 是一种内建约束 comparable ,代表任意可比较类型。
comparable 是一种很有用的类型约束,满足这种约束的类型 T 可以使用 ==
和 !=
运算符进行比较。下面这个例子,我们通过逐一比较,从切片元素中找出指定值。通过类型参数 T ,Index 函数可以支持任意可比较类型。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
|
package main
import "fmt"
// Index returns the index of x in s, or -1 if not found.
func Index[T comparable](s []T, x T) int {
for i, v := range s {
// v and x are type T, which has the comparable
// constraint, so we can use == here.
if v == x {
return i
}
}
return -1
}
func main() {
// Index works on a slice of ints
si := []int{10, 20, 15, -10}
fmt.Println(Index(si, 15))
// Index also works on a slice of strings
ss := []string{"foo", "bar", "baz"}
fmt.Println(Index(ss, "hello"))
}
|
泛型类型
除了泛型函数,Go 语言还支持 泛型类型 。泛型类型,顾名思义就是带有类型参数的类型定义,设计泛型数据结构时非常有用。
下面是一个简单泛化类型示例,它定义了一个可以保存任意类型的单链表节点:
1
2
3
4
5
6
7
8
9
10
11
|
package main
// List represents a singly-linked list that holds
// values of any type.
type List[T any] struct {
next *List[T]
val T
}
func main() {
}
|
练习
您可为例子中的链表添加若干函数,来实现单链表功能,以此练练手。
参考答案
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
|
package main
import (
"fmt"
)
// List represents a singly-linked list that holds
// values of any type.
type List[T any] struct {
next *List[T]
val T
}
// create nil list of type T
func NewList[T any] () *List[T] {
return nil
}
// insert val before list
func (list *List[T]) Insert(val T) (*List[T]) {
return &List[T]{
next: list,
val: val,
}
}
// insert val after list
func (list *List[T]) Append(val T) (*List[T]) {
if (list == nil) {
return list.Insert(val)
}
node := &List[T] {
next: list.next,
val: val,
}
list.next = node
return list
}
// return new list with elements reversed
func (list *List[T]) Reverse() *List[T] {
var reversed *List[T]
for cursor := list; cursor != nil; cursor = cursor.next {
reversed = reversed.Insert(cursor.val)
}
return reversed
}
// traverse list one by one
func (list *List[T]) Traverse(f func (val T, l *List[T])) {
for cursor := list; cursor != nil; cursor=cursor.next {
f(cursor.val, cursor)
}
}
// print list
func (list *List[T]) Print() {
list.Traverse(func (val T, _ *List[T]) {
fmt.Printf("%s ", val)
})
}
// print list with line break
func (list *List[T]) Println() {
list.Print()
fmt.Println()
}
func main() {
// initialize a new list
l := NewList[string]().Insert("apple").Insert("banana").Append("cat")
// print it
l.Println()
// reverse it
l = l.Reverse()
// print it again
l.Println()
}
|
总结
Go 语言 1.18 版本开始支持 泛型 编程,可以定义 泛型函数 和 泛型类型 !泛型函数是带有类型参数的函数,能够处理多种数据类型。泛型类型则是带有类型参数的类型,可以用来实现泛化的数据结构。
【小菜学Go语言】系列文章首发于公众号【小菜学编程】,敬请关注: