跳转至

Golang 速成 | 泛型

Golang 在 1.18 版本引入了泛型(Generics),这是一种允许你编写能够处理多种类型的代码的特性,而无需牺牲类型安全性和性能。泛型通过类型参数来实现,类型参数使函数和数据结构可以在多种类型上操作。以下是 Go 泛型的基本介绍:

基本语法

在 Go 中,你可以使用类型参数来定义泛型函数和泛型类型。类型参数使用方括号 [] 包围,并在函数名或类型名之后紧跟。

Go
// 泛型函数
func Print[T any](s []T) {
    for _, v := range s {
        fmt.Println(v)
    }
}

// 泛型类型
type List[T any] struct {
    elements []T
}

func (l *List[T]) Add(element T) {
    l.elements = append(l.elements, element)
}

类型约束

Go 中的泛型允许你对类型参数进行约束,以限制可以传递给类型参数的类型。最基本的约束是 any ,它表示可以是任何类型。你也可以使用接口作为约束。

Go
1
2
3
4
5
6
7
type Number interface {
    int | int32 | int64 | float32 | float64
}

func Sum[T Number](a, b T) T {
    return a + b
}

使用示例

以下是一个使用泛型的简单示例,展示了如何创建泛型函数和类型,并如何使用它们。

Go
package main

import "fmt"

// 泛型函数
func Print[T any](s []T) {
    for _, v := range s {
        fmt.Println(v)
    }
}

// 泛型类型
type List[T any] struct {
    elements []T
}

func (l *List[T]) Add(element T) {
    l.elements = append(l.elements, element)
}

func main() {
    // 使用泛型函数
    // 此处编译器可以根据传递的参数自动推断出 T 的类型
    // 所以不用写为Print[[]int]([]int{1, 2, 3, 4})
    Print([]int{1, 2, 3, 4})
    Print([]string{"a", "b", "c"})

    // 使用泛型类型
    // List[int] 表示创建了泛型类型 List 的一个实例,其中类型参数 T 被替换为 int。
    // List[int] 代表一个整型列表。
    // List[int]{} 部分初始化了一个空的 List[int] 实例。
    intList := List[int]{}
    intList.Add(1)
    intList.Add(2)
    fmt.Println(intList.elements)

    stringList := List[string]{}
    stringList.Add("hello")
    stringList.Add("world")
    fmt.Println(stringList.elements)
}

泛型优点

  • 代码复用:通过泛型,可以编写更通用的代码,而不需要为每种类型重复实现相同的逻辑。
  • 类型安全:泛型提供了编译时的类型检查,避免了运行时类型错误。
  • 性能:Go的泛型实现不会引入额外的性能开销,保持了Go语言高效的运行性能。

总之,Go引入泛型为开发者提供了更强大的工具来编写高效、可重用且类型安全的代码。通过泛型,开发者可以在保持代码清晰简洁的同时,提高代码的灵活性和可维护性。