如何对受联合约束的类型参数使用类型推断?

问题描述 投票:0回答:1

例如:

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 generics
1个回答
0
投票

类型推断不适用于约束没有核心类型的情况。这可能需要一个多项式时间求解器,这对于 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)
}
© www.soinside.com 2019 - 2024. All rights reserved.