例如:
type AnyPtr[T any] interface {
*T
}
type AnyPtrSlice[T any] interface {
[]*T
}
func FuncName[T AnyPtr[E] | AnyPtrSlice[E], E any](data T) (err error) {
}
type ModelAA struct {
A int
B int
}
func TestAddV2(t *testing.T) {
var a = ModelAA{
A: 1, B: 2,
}
_ = FuncName(&a)
}
这种方式会被编译器报无法推断E,还有其他写法吗?
希望有办法解决。我希望它不会被分成多种方法。
类型推断不适用于约束没有核心类型的情况。这可能需要一个多项式时间求解器,这对于 Go 快速编译时间的承诺来说并不好。
联合约束,例如
*T | []*T
,本质上与T AnyPtr[E] | AnyPtrSlice[E]
相同,没有核心类型。强调我的:
如果满足以下条件之一,则接口 T 具有核心类型:
- 有一个单一类型U,它是T类型集中所有类型的底层类型;或
- T 的类型集仅包含具有相同元素类型 E 的通道类型,并且所有有向通道具有相同的方向。
没有其他接口具有核心类型。
请注意,当您直接在类型参数列表中编写联合时
FuncName[T AnyPtr[E] | AnyPtrSlice[E], E any]
,这是语法糖。相当于写:
type C[T any] interface {
AnyPtr[T] | AnyPtrSlice[T]
}
func FuncName[E any, T C[E]](data T) error {}
您可以看到接口
C
中的术语是 *T
,其基础类型是其本身,以及 []*T
,其基础类型是其本身。但这些底层类型不同,因此 C
没有核心类型。
当类型推断不起作用时,您必须显式实例化类型参数。如果将类型参数
E
移动到列表的开头,这将是唯一显式必需的类型参数,然后可以从中推断出 T
。
// move E at the beginning of the type param list
func FuncName[E any, T AnyPtr[E] | AnyPtrSlice[E]](data T) error {
return nil
}
func TestAddV2(t *testing.T) {
a := ModelAA{}
// supply a type argument for E
_ = FuncName[ModelAA](&a)
}