Golang 泛型
- 类型参数
T any
- 任意类型T int | int8
- 其中之一T ~int
- 允许衍生类型 - 例如type Age int
- 参考
caution
- 目前不好使用 new(T), 增加一个类型进行限制
- method 不支持类型参数 - No parameterized methods
- type 参数不支持 assert - 可以考虑
_,ok := any(v).(int)
info
FAQ
new(T)
- 直接限定不方便传参数,因为 struct 不一定实现 interface,
*struct
才实现 interface
正确做法
type Setter[T any] interface {
SetIndex(n int)
*T
}
func setIndex[T any, PT Setter[T]](items []int) (o []PT) {
for _, v := range items {
m := PT(new(T))
m.SetIndex(v)
o = append(o, m)
}
return
}
// 限定 接口 直接写也可以
func setIndex[T any, PT interface {
SetIndex(n int)
*T
}](items []int) (o []PT) {
for _, v := range items {
m := PT(new(T))
m.SetIndex(v)
o = append(o, m)
}
return
}
错误做法
func setIndex[M interface {
SetIndex(n int)
}](items []int) (o []M) {
for _, v := range items {
// NPE
m := *new(M)
m.SetIndex(v)
o = append(o, m)
}
return
}
type A struct {
Index int
}
func (s *A) SetIndex(v int) {
s.Index = v
}
func TestSetIndex(t *testing.T) {
// 会出现 NPE
fmt.Println(setIndex[*A]([]int{1, 2, 3, 4}))
}
method must have no type parameters
- func 支持类型参数
- method 不支持类型参数
- 只能使用 struct 上的类型参数
- No parameterized methods
type A struct{}
// method 不支持 类型参数
func (v A)Map[T any](f func(A)T)T{
return f(v)
}
// func 支持 类型参数
func Map[IN any, OUT any](s IN, f func(IN) OUT) (o OUT) {
return f(s)
}
cannot use generic type without instantiation
type A[T any] struct {}
// 不可以
func(a A)Name(){}
// 可以
func(a A[T])Name(){}
cannot use type assertion on type parameter value Xxx(variable of type T constrained by any)
type A[T any] struct {
Val T
}
func(a A[T])Name(){
// 不可以 - 因为 T 是具体类型
_,_=a.Val.(string)
// 可以
var v interface{} = a.Val
_, _ = v.(string)
// 可以
_, _ = (interface{})(a.Val).(string)
}
- proposal: spec: generics: type switch on parametric types #45380