目录
1、类型约束
2、泛型函数
3、泛型结构体
4、泛型接口
5、以接口作为类型约束
关键词:泛型、类型参数、类型约束
Go 语言在 1.18 版本引入了泛型(Generics)特性,可以编写更通用、可复用的代码,泛型可以用于:泛型函数、泛型结构体、泛型接口。
1、类型约束
在 Go 泛型中,类型参数需要满足一定的约束条件才能被正确使用。常见的约束有:
comparable:comparable
约束要求类型参数必须是可比较的类型,即可以使用==
和!=
进行比较的类型,比如整数、字符串、布尔值等。
any:any
约束表示类型参数可以是任意类型,它是最宽松的一种约束条件。当定义泛型接口、结构体等时,如果希望允许任何类型作为类型参数,就可以使用any
约束。
此外,还可以自定义类型约束来满足更复杂的需求,通过定义接口并在接口中定义一组方法要求,然后让类型参数满足该接口的要求来实现自定义约束。
常用组合:[T comparable]、[T, U comparable]、[T, U any]、[T any, U comparable]、[T MyInterface]
2、泛型函数
在函数名后面,中括号中指定:类型参数、类型约束。
在很多情况下,编译器可以根据实参自动推断类型参数的值,这样就不需要显式地指定类型参数。
//单类型参数
func Compare[T comparable](a, b T) bool {
return a == b
}
//显示指定类型参数
Compare[int](5, 5)
Compare[string]("hello", "hello")
//自动推断类型参数
Compare(5, 5)
Compare("hello", "hello")
//多类型参数
func Compare[T comparable, U any](a, b T, c U) bool {
fmt.Println("c:", c)
return a == b
}
//显示指定类型参数
Compare[int, string](1, 2, "c")
//自动推断类型参数
Compare[int](1, 2, "c")
3、泛型结构体
定义包含类型参数的结构体,以便在结构体内部使用不同类型的数据。
在结构体名后面,中括号中指定:类型参数、类型约束。
在内部成员中,使用类型参数。
// 泛型结构体
type Pair[T, U any] struct {
First T //泛型T成员变量
Second U //泛型U成员变量
}
// 泛型成员函数
func (p *Pair[T, U]) print(a T, b U) {
fmt.Println(p.First)
fmt.Println(p.Second)
fmt.Println(a)
fmt.Println(b)
}
func main() {
p := Pair[string, int]{
First: "a",
Second: 1,
}
p.print("b", 2)
}
4、泛型接口
泛型接口可以定义一组方法,这些方法可以使用类型参数来处理不同类型的数据。
在接口名后面,中括号中指定:类型参数、类型约束。
在内部成员方法中,使用类型参数。
type PairInterface[T, U any] interface {
Print(T, U)
}
// 泛型结构体
type Pair[T, U any] struct {
First T //泛型T成员变量
Second U //泛型U成员变量
}
// 泛型成员函数
func (p *Pair[T, U]) Print(a T, b U) {
fmt.Println(p.First)
fmt.Println(p.Second)
fmt.Println(a)
fmt.Println(b)
}
func main() {
p := Pair[string, int]{
First: "a",
Second: 1,
}
p.Print("b", 2)
}
5、以接口作为类型约束
以接口作为【类型约束】,可以在接口中定义一组方法,只有实现了接口的结构体类型才可以作为【类型参数】。
如下,泛型函数 DoMath 的类型参数 T 的约束类型为接口 Mathable,Interger 实现了接口 Mathable,因此可以作为泛型函数 DoMath 的类型参数。
package main
import "fmt"
// Mathable接口定义了Add和Subtract两个方法要求,作为自定义类型约束
type Mathable interface {
Add(other Mathable) Mathable
Subtract(other Mathable) Mathable
}
// DoMath函数,T是类型参数且必须满足Mathable约束
func DoMath[T Mathable](a, b T) T {
return a.Add(b).Subtract(b)
}
// Integer结构体实现了Mathable接口
type Integer struct {
value int
}
func (i *Integer) Add(other *Integer) *Integer {
return &Integer{value: i.value + other.value}
}
func (i *Integer) Subtract(other *Integer) *Integer {
return &Integer{value: i.value - other.value}
}
func main() {
a := Integer{value: 5}
b := Integer{value: 3}
result := DoMath(&a, &b)
fmt.Println(result.value)
}