golang泛型基本用法

作者:matrix 发布时间:2025-05-31 分类:Golang

Golang在1.18版本中就引入了泛型的支持,现在开发使用版本都是1.23,1.24 平时写的时候还是知之甚少~ 这几天又看到GOrm v1.30.0版本中也加入了泛型支持 不错不错 😆 📝

泛型声明

普通函数的泛型

func Print[T any](value T) {
    fmt.Println(value)
}

T 即表示泛型,不确定的类型,调用的时候指定

any 表示对T的约束,这里即表示没有任何约束的特殊约束

结构体中的泛型

type Box[T any] struct {
    value T
}

支持结构体的字段类型的泛型。
Box 是一个泛型结构体,其字段 value 的类型是 T

实例化时指定
// 举例:实例化 Box[int]
boxInt := Box[int]{value: 42}
fmt.Println("Box[int]:", boxInt.Value)

这里类型指定非必需,不指定类型时go会自己完成参数类型推导

结构体方法中的泛型

允许使用结构体泛型

func (b *Box[T]) SetValue(value T) {
    b.value = value
}

这里SetValue 是 Box[T] 的方法,它使用了结构体的泛型参数 T
 

注意:golang不支持结构体方法中独立的泛型参数

// 错误:Go 不支持在方法中声明独立的泛型参数
func (b *Box[T]) SetValue[K any](key K) {
    // ...
}

这里的K就是独立的泛型参数,因为在结构体中没有声明就会报错

泛型约束

自定义约束

一般泛型类型的约束any 表示任意类型用的比较多,不过也可以自定义约束类型

比如自定义的类型约束 CType: 仅允许 uintstring 和 float64和自定义类型 myint

type myint int32
type CType interface{
~uint | ~string | ~float64 | myint
}
  • ~ 表示近似约束(Approximation Constraint)(只有底层类型才允许这样声明),~string 意思是只要底层类型是string的都允许,这里~的表达意思其实和nginx中的匹配规则异曲同工

  • 没有~ 表示准确约束,CType中的myint 意思是只允许myint类型,底层int类型都不行

使用时也可以简写省略interface 参考下面的[[### 其他高级用法]]

其他内置约束

除了自定义也有很多可用的其他内置约束。

comparable 约束:支持 ==,!=操作符的类型

其他常用约束:golang.org/x/exp/constraints

函数约束

限制其必须实现指定方法,其实就是接口interface的约束

type Stringer interface {
    String() string
}

func myprin2[T Stringer](value T) {
    fmt.Println(value)
}

除了类型约束之外 还可以约束是否实现指定方法,这里即对T约束 必需实现String() 方法

交集约束

还可以进行交集约束,也就是多个约束条件必须都满足。

type StringableSignedInteger interface {
    ~int | ~int8 | ~int16 | ~int32 | ~int64 //约束 底层int类型
    String() string //约束 必须实现String方法
}

func myprin23[T StringableSignedInteger](value T) {
    fmt.Println(value)
}


type myint int
func (m myint) String() string {
    return fmt.Sprintf("%d", m)
}


func main(){
    myprin23[myint](1)
    myprin23(myint(1))
}

上面例子中的StringableSignedInteger约束:
底层类型必需为底层*int类型(~int | ~int8 | ~int16 | ~int32 | ~int64),并且要实现String()方法

其他高级用法

避免创建interface 可以如下 简写,约束为:int | ~string


func myprin3[T interface{ int | ~string }](value T) { fmt.Println(value) } func myprin33[T int | ~string](value T) { fmt.Println(value) }

参考:

https://taoshu.in/go/generics/design.html
https://github.com/sesopenko/genericpubsub