文章目录
- Go 的泛型
- 1. 泛型的介绍
- 2. Go 的泛型
- 3. 泛型函数
- 4. 泛型类型
- 5. 泛型接口
- 6. 泛型结构体
- 7. 泛型约束
- 8. 泛型函数的类型推断
Go 的泛型
1. 泛型的介绍
泛型是一种编程范式,它将类型参数化,可以用于编写灵活且可重用的函数或数据结构,这样我们就可以用自己的类型来代替那些被硬编码的类型。
泛型的好处是可以在编译时期发现类型不匹配的错误,而不是在运行时期。
2. Go 的泛型
Go 语言的泛型是通过类型参数化实现的,它的类型参数化的方式是通过在函数名后面加上类型参数列表实现的,例如:
func Swap[T any](x, y T) (T, T) {
return y, x
}
上面的代码中,T
就是类型参数,它可以是任意类型,any
是类型约束,表示T
必须是任意类型。
3. 泛型函数
泛型函数是指可以接受任意类型的函数,例如:
func Map[T, U any](f func(T) U, list []T) []U {
newList := make([]U, len(list))
for i, v := range list {
newList[i] = f(v)
}
return newList
}
上面的代码中,Map
函数接受一个函数f
和一个list
,f
函数接受一个T
类型的参数,返回一个U
类型的值,list
是一个T
类型的切片,Map
函数返回一个U
类型的切片。
4. 泛型类型
泛型类型是指可以接受任意类型的类型,例如:
type Stack[T any] []T
func (s *Stack[T]) Push(v T) {
*s = append(*s, v)
}
func (s *Stack[T]) Pop() T {
v := (*s)[len(*s)-1]
*s = (*s)[:len(*s)-1]
return v
}
上面的代码中,Stack
类型接受一个类型参数T
,它是一个切片类型,Push
方法接受一个T
类型的参数,Pop
方法返回一个T
类型的值。
5. 泛型接口
泛型接口是指可以接受任意类型的接口,例如:
type Container[T any] interface {
Put(v T)
Get() T
}
type Stack[T any] []T
func (s *Stack[T]) Put(v T) {
*s = append(*s, v)
}
func (s *Stack[T]) Get() T {
v := (*s)[len(*s)-1]
*s = (*s)[:len(*s)-1]
return v
}
上面的代码中,Container
接口接受一个类型参数T
,它有两个方法,Put
方法接受一个T
类型的参数,Get
方法返回一个T
类型的值,Stack
类型接受一个类型参数T
,它是一个切片类型,Put
方法接受一个T
类型的参数,Get
方法返回一个T
类型的值。
6. 泛型结构体
泛型结构体是指可以接受任意类型的结构体,例如:
type Pair[T1, T2 any] struct {
First T1
Second T2
}
func main() {
p1 := Pair[int, string]{1, "hello"}
p2 := Pair[int, string]{2, "world"}
fmt.Println(p1, p2)
}
上面的代码中,Pair
结构体接受两个类型参数T1
和T2
,它有两个字段,First
字段的类型是T1
,Second
字段的类型是T2
。
7. 泛型约束
泛型约束是指对泛型的类型进行约束,例如:
func Max[T comparable](x, y T) T {
if x > y {
return x
}
return y
}
上面的代码中,Max
函数接受两个T
类型的参数,返回一个T
类型的值,T
类型必须是可比较的。
8. 泛型函数的类型推断
泛型函数的类型推断是指在调用泛型函数时,可以根据传入的参数类型推断出泛型函数的类型,例如:
func main() {
fmt.Println(Max(1, 2))
fmt.Println(Max(1.1, 2.2))
fmt.Println(Max("hello", "world"))
}
上面的代码中,Max
函数接受两个T
类型的参数,返回一个T
类型的值,T
类型必须是可比较的,但是我们在调用Max
函数时并没有指定T
的类型,但是编译器可以根据传入的参数类型推断出T
的类型,所以我们可以直接调用Max
函数。