在 Go 语言中,泛型(Go 1.18 引入)允许编写可处理多种类型的函数,而无需为每种类型单独实现。以下是泛型函数调用的核心要点和示例解析:
1. 泛型函数调用语法在调用泛型函数时,需显式指定类型参数(若编译器可自动推断则可省略):
funcName[T1, T2, ...](arg1, arg2, ..., argN)- funcName:泛型函数名。
- T1, T2, ...:类型参数(如 int、string 或自定义约束类型)。
- arg1, arg2, ..., argN:实际参数,需与类型参数匹配。
2. 泛型函数定义示例示例 1:通用 min 函数package mainimport "fmt"// 定义 Ordered 接口约束可比较类型type Ordered interface { ~int | ~int8 | ~int16 | ~int32 | ~int64 | ~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64 | ~float32 | ~float64 | ~string}// 泛型 min 函数,T 必须满足 Ordered 约束func min[T Ordered](a, b T) T { if a < b { return a } return b}func main() { fmt.Println(min[int](1, 2)) // 显式指定类型:输出 1 fmt.Println(min("hello", "hi")) // 类型推断:输出 "hello"}- 关键点:
Ordered 接口通过 | 定义允许的类型集合。
~ 表示允许底层类型匹配(如自定义类型 type MyInt int)。
调用时可显式指定类型(如 min[int])或依赖编译器推断。
示例 2:多类型参数泛型函数func PrintPair[T any, U any](a T, b U) { fmt.Printf("(%v, %v)n", a, b)}func main() { PrintPair[int, string](1, "one") // 输出:(1, one) PrintPair(true, 3.14) // 类型推断:输出:(true, 3.14)}3. 泛型调用的注意事项- 类型推断:若参数类型明确,可省略类型参数(如 min("a", "b"))。
- 约束接口:通过接口定义类型行为(如 Ordered 确保 <= 操作合法)。
- 性能:泛型在编译期生成具体类型代码,无运行时开销。
- 限制:
不能直接使用基本类型作为类型参数(需通过接口约束)。
复杂类型约束可能导致编译时间增加。
4. 泛型的优势- 代码复用:避免为不同类型重复实现逻辑。
- 类型安全:编译期检查类型约束,减少运行时错误。
- 清晰性:明确函数支持的类型范围。
5. 常见问题Q:如何传递自定义类型?若自定义类型底层是 Ordered 支持的类型(如 type ID int),可直接使用:
type ID intfunc main() { fmt.Println(min(ID(1), ID(2))) // 输出:1}Q:泛型与接口的区别?- 接口:运行时多态,通过方法集匹配类型。
- 泛型:编译时多态,通过类型参数生成具体代码,更高效。
总结Go 的泛型通过显式类型参数或推断,在函数调用中提供灵活的类型处理能力。结合接口约束(如 Ordered),既能保证类型安全,又能简化代码。掌握泛型语法和约束设计,可显著提升代码的复用性和可维护性。