511 字
3 分钟
Go泛型介绍
2025-01-11

Go泛型介绍#

go语言泛型#

1.18 版本开始,Go 语言正式支持泛型,为开发者带来了更强大、更灵活的编程能力. 泛型是一种编程语言的特性,它允许我们编写能够处理多种类型的代码,而不是只针对特定类型编写的代码。 泛型主要基于类型参数实现,通过在函数、接口或数据结构定义中添加类型参数,我们可以实现通用的代码逻辑,使其适用于各种数据类型。

函数泛型#

例如我们可以利用泛型编写一个通用的交换函数swap

func Swap[T any](a, b *T) {
*a, *b = *b, *a
}

函数名后 T 是一个类型参数,any 表示 T 可以是任何类型 我们也可以约束它的类型参数,比如我只接收intstring类型的参数

func Swap2[T int | string](a, b *T) {
*a, *b = *b, *a
}

这样如果传入的参数非intstring类型就会报错:

Cannot use [] int as the type interface{ int | string } Type does not implement constraint interface{ int | string } because type is not included in type set (int, string)

假如我们要约束的类型很多,我们还可以使用接口将这些类型单独封装

type Swapable interface {
~int | string
}
func Swap2[T Swapable | string](a, b *T) {
*a, *b = *b, *a
}

其中~int的意思也包括基于int类型的其他派生类型

结构体泛型#

可以利用泛型创建通用的列表、映射、堆栈等数据结构,它们可以存储任意类型的值。例如,我们可以定义一个通用的栈结构体:

package generic
import "fmt"
type Stack[T any] struct {
data []T
}
func NewStack[T any]() *Stack[T] {
return &Stack[T]{}
}
func (s *Stack[T]) Push(item T) {
s.data = append(s.data, item)
}
func (s *Stack[T]) Pop() T {
if len(s.data) == 0 {
panic("stack is empty")
}
item := s.data[len(s.data)-1]
s.data = s.data[:len(s.data)-1]
return item
}
func (s *Stack[T]) String() string {
return fmt.Sprintf("%v", s.data)
}

使用示例:

package generic
import "testing"
func TestStack(t *testing.T) {
s := NewStack[int]()
s.Push(1)
s.Push(2)
t.Log(s.String())
t.Log(s.Pop())
}