Go语言在1.18版本中正式引入了泛型(Generics)特性。泛型允许你编写可以处理多种类型的代码,而无需为每种类型重复编写相同的逻辑。在Go中,泛型主要通过类型参数(type parameters)来实现。

一、核心概念

1.类型参数(Type Parameters) 用方括号 [] 声明泛型类型参数:

   func PrintSlice[T any](s []T) {
       for _, v := range s {
           fmt.Println(v)
       }
   }
  • T anyT 是类型参数,any 表示约束(任意类型)。

2.类型约束(Type Constraints) 限制可用的类型范围:

   type Number interface {
       int | float64
   }

   func Sum[T Number](s []T) T {
       var sum T
       for _, v := range s {
           sum += v
       }
       return sum
   }
  • int | float64T 只能是 int 或 float64

3.可比较类型(Comparable Types) 使用内置 comparable 约束支持 == 和 !=:

   func FindIndex[T comparable](s []T, target T) int {
       for i, v := range s {
           if v == target {
               return i
           }
       }
       return -1
   }

需要安装golang.org/x/exp/constraints模块。

go get golang.org/x/exp/constraints

二、关键语法

  • 泛型函数
  func Swap[T any](a, b T) (T, T) {
      return b, a
  }
  • 泛型类型:
  type Stack[T any] struct {
      items []T
  }

  func (s *Stack[T]) Push(item T) {
      s.items = append(s.items, item)
  }
  • 接口约束
  type Stringer interface {
      String() string
  }

  func ToString[T Stringer](v T) string {
      return v.String()
  }

三、使用场景

1.通用数据结构 (栈、队列、链表等)

   type Queue[T any] struct {
       items []T
   }
   func (q *Queue[T]) Enqueue(item T) {
       q.items = append(q.items, item)
   }

2.算法复用 (排序、搜索、比较等)

   func Max[T constraints.Ordered](a, b T) T {
       if a > b {
           return a
       }
       return b
   }

3.减少重复代码 避免为不同类型写相同逻辑的函数。

四、完整示例

package main

import (
    "fmt"
    "golang.org/x/exp/constraints"
)

// 泛型函数:求最大值
func Max[T constraints.Ordered](a, b T) T {
    if a > b {
        return a
    }
    return b
}

// 泛型类型:动态数组
type DynamicArray[T any] struct {
    data []T
}

func (da *DynamicArray[T]) Append(item T) {
    da.data = append(da.data, item)
}

func main() {
    // 使用 Max 函数
    fmt.Println(Max(3, 7))           // 7
    fmt.Println(Max(2.8, 1.5))       // 2.8

    // 使用 DynamicArray
    arr := DynamicArray[int]{}
    arr.Append(10)
    arr.Append(20)
    fmt.Println(arr.data) // [10 20]
}

需要导入实验性约束包:go get golang.org/x/exp/constraints

核心功能解析

1.定义泛型结构体 DynamicArray:

type DynamicArray[T any] struct {
    data []T
}
  • DynamicArray 是一个泛型结构体,其中 T any 表示它可以存储任何类型的元素。
  • 结构体中有一个字段 data,它是一个切片(slice),可以动态地增长和收缩,用于存储数组的元素。

2.定义 Append 方法:

func (da *DynamicArray[T]) Append(item T) {
    da.data = append(da.data, item)
}
  • Append 方法用于向 DynamicArray 中添加一个元素。
  • da *DynamicArray[T] 表示接收者是指向 DynamicArray 结构体的指针
  • item T 是要添加的元素,其类型与 DynamicArray 的泛型参数 T 一致。
  • 方法内部调用 append 函数将新元素添加到 data 切片中。

3.主函数 main:

func main() {
    // 使用 Max 函数
    fmt.Println(Max(3, 7))     // 7
    fmt.Println(Max(2.8, 1.5)) // 2.8

    // 使用 DynamicArray
    arr := DynamicArray[int]{}
    arr.Append(10)
    arr.Append(20)
    fmt.Println(arr.data) // [10 20]
}
  • 调用了 Max 函数两次,分别比较了两个整数和两个浮点数,输出了它们的最大值。
  • 创建了一个 DynamicArray 的实例 arr,并指定了实例的类型为 int。这意味着 arr 只能存储整型数据。
Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐