← Backend / Go / 基础专题

21_泛型与类型约束

理解类型参数、约束和适合使用泛型的场景。

Go 基础专题 21:泛型与类型约束

学习目标:理解类型参数、约束和适合使用泛型的场景。

核心知识

泛型让同一算法服务于多种类型,而编译器仍能检查类型。类型参数写在函数名后的方括号中,约束规定允许的类型或方法。最简单的约束是 any,但若函数要比较大小,必须使用支持相应运算的约束。

package main

import "fmt"

func First[T any](values []T) (T, bool) {
    if len(values) == 0 {
        var zero T
        return zero, false
    }
    return values[0], true
}

func main() {
    value, ok := First([]string{"Go", "Python"})
    fmt.Println(value, ok)
}

泛型适合容器、算法和确实重复的类型安全逻辑。若差异在行为而非数据类型,接口可能更合适;若只有两处简单代码,先写清楚再抽象。comparable 允许 ==、!=,可用作 map 键约束。类型集合可以写 ~int | ~int64 等,~ 表示底层类型相同的自定义类型也符合。

在使用泛型前先确认目标 Go 版本支持所需语法。函数调用通常可推断类型参数,无法推断时可显式写 First[string](values)。

逐步理解

泛型示例在空切片时返回 var zero T,因此调用方必须看 ok,不能仅凭返回值判断存在。类型参数并不意味着“所有运算都可用”;约束 any 只能保证这个值可保存和传递,若要比较大小就需更窄的约束。接口表达共同行为,泛型表达跨类型复用算法。

动手练习

练习:写 Last[T any],空切片时返回零值和 false。答案要点:结构与 First 相同,只把索引改成 len(values)-1。