简单的Golang泛型教程

1 分钟阅读

Golang泛型教程

Golang是一门比较年轻的编程语言,在经过长期的发展之后,其在各个领域都已经得到了广泛应用。Golang的1.17版本开始引入泛型特性的支持。

Golang泛型主要有以下几个方面的应用:

  • 函数和方法的泛型声明
  • 接口的泛型声明
  • 结构体和嵌入的泛型

接下来,我们将会深入探究这些方面的内容,并且通过简单的示例代码来演示Golang泛型的用法。

函数和方法的泛型声明

在Golang 1.17之前,Golang的函数和方法中只支持使用具体类型进行声明,在函数内部也都只能使用特定类型的变量或参数。而引入泛型之后,Golang的函数和方法中就可以使用泛型类型进行声明了。

泛型函数

在函数中使用泛型类型进行声明的语法为:

1
2
3
func 函数名[T any](参数列表) 返回值类型 {
    // 函数体
}

其中,T代表任意类型,可以在函数内部用于声明变量或参数。

下面是一个示例代码,演示了如何在函数中使用泛型:

1
2
3
4
5
6
7
8
9
10
11
func Swap[T any](a, b *T) {
    *a, *b = *b, *a
}

func main() {
    // 使用泛型函数
    a := 1
    b := 2
    Swap(&a, &b)
    fmt.Println(a, b)
}

这段代码中,我们声明了一个名为Swap的泛型函数,该函数接收两个指向任意类型的变量的指针,并且使用*操作符进行变量内容的交换。在实际调用该函数的时候,我们传递了两个int类型的指针,使得ab的值进行了交换。

泛型方法

对于方法而言,我们同样可以使用泛型类型进行声明。在方法中使用泛型类型进行声明的语法为:

1
2
3
4
func (接收者类型) 方法名[T any](参数列表) 返回值类型 {
    // 函数体
}

其中,T代表任意类型,并且可以在方法内部用于声明变量或参数。

下面是一个示例代码,演示了如何在方法中使用泛型:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
type Stack[T any] []T

func (s *Stack[T]) Push(v T) {
    *s = append(*s, v)
}

func (s *Stack[T]) Pop() T {
    index := len(*s) - 1
    res := (*s)[index]
    *s = (*s)[:index]
    return res
}

func main() {
    // 使用泛型方法
    var s Stack[int]
    s.Push(1)
    s.Push(2)
    s.Push(3)
    fmt.Println(s.Pop())
    fmt.Println(s.Pop())
}

这段代码中,我们声明了一个名为Stack的泛型类型,并且在其中声明了两个泛型方法PushPop。这两个方法都使用了T作为自己的泛型类型,使得方法可以适用于任意类型。在实际使用的时候,我们通过Stack[int]来声明一个类型为int的栈,并且对其进行了相应的操作。

接口的泛型声明

在Golang 1.17后,我们还可以使用泛型类型来声明接口。在这种情况下,我们可以使用type关键字来定义一个代表任意类型的泛型类型,并且在接口中使用该类型来进行声明。

下面是一个示例代码,演示了如何在接口中使用泛型:

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
type Container[T any] interface {
    Get() T
    Put(v T)
}

type Stack[T any] []T

func (s *Stack[T]) Push(v T) {
    *s = append(*s, v)
}

func (s *Stack[T]) Pop() T {
    index := len(*s) - 1
    res := (*s)[index]
    *s = (*s)[:index]
    return res
}

func (s *Stack[T]) Get() T {
    return s.Pop()
}

func (s *Stack[T]) Put(v T) {
    s.Push(v)
}

func main() {
    // 使用泛型接口
    var c Container[int] = new(Stack[int])
    c.Put(1)
    c.Put(2)
    fmt.Println(c.Get())
    fmt.Println(c.Get())
}

这段代码中,我们声明了一个名为Container的泛型接口,并且在其中声明了GetPut两个方法,这两个方法都使用了T作为自己的泛型类型。而在Stack类型的实现中,我们同样实现了GetPut方法,并且额外声明了一个方法Pop,用于从栈中获取元素。在实际使用中,我们通过Container[int]声明了一个类型为int的容器,并且使用Stack[int]实现了该容器。

结构体和嵌入的泛型

在Golang 1.17后,我们还可以在结构体和嵌入中使用泛型类型进行声明。这种情况下,我们可以使用与函数和方法类似的语法进行声明。

下面是一个示例代码,演示了如何在结构体和嵌入中使用泛型:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
type Pair[T any] struct {
    first T
    second T
}

type IntPair struct {
    Pair[int]
}

func main() {
    // 使用结构体和嵌入的泛型
    p := IntPair{Pair[int]{1, 2}}
    fmt.Println(p.first, p.second)
}

这段代码中,我们声明了一个名为Pair的泛型结构体,并且定义了一个包含两个成员变量firstsecond的结构体。在IntPair类型的定义中,我们嵌入了Pair[int],使得IntPair类型包含了两个类型为int的成员变量。在实际使用中,我们通过IntPair{Pair[int]{1, 2}}来创建一个类型为IntPair的变量p,并且获取了其中的两个成员变量。

总结

到此为止,我们已经讲解了在Golang 1.17中泛型的主要应用场景,包括函数、方法、接口、结构体和嵌入。在实际开发中,我们可以使用这些泛型来提高程序的可扩展性和可重用性,从而让程序更加灵活和具有适应性。如果您还没有尝试过使用Golang中的泛型,那么不妨在接下来的代码中尝试一下吧!

知识共享许可协议

本作品采用 知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议 进行许可。欢迎转载、使用、重新发布,但务必保留文章署名 TinyZ Zzh (包含链接: https://tinyzzh.github.io ),不得用于商业目的,基于本文修改后的作品务必以相同的许可发布。 如有任何疑问,请 与我联系 (tinyzzh815@gmail.com)

TinyZ Zzh

TinyZ Zzh

专注于高并发服务器、网络游戏相关(Java、PHP、Unity3D、Unreal Engine等)技术,热爱游戏事业, 正在努力实现自我价值当中。

评论

  点击开始评论...