无法推断函数构造函数的泛型参数中的类型

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

我在 Go 中有一些通用代码,其中有一个具有通用参数的“主”类型和许多应共享相同通用参数的“从”类型。代码看起来类似于:

type Doer[T any] interface {
    ModifyA(*A[T])
}

type B[T any] struct {
}

func NewB[T any]() *B[T] {
    return new(B[T])
}

func (b *B[T]) ModifyA(a *A[T]) {
    // Do a thing
}

type A[T any] struct{}

func NewA[T any]() A[T] {
    return A[T]{}
}

func (a *A[T]) Run(doers ...Doer[T]) {
    for _, doer := range doers {
        doer.ModifyA(a)
    }
}

func main() {
    a := new(A[int])
    a.Run(NewB())   // error here
}

基本上,用户应该在

T
上定义
A
然后在
T
上定义
B
应该是相同的。这种代码可以在其他支持泛型的语言中运行,但在 Go 中,我在注释行中得到一个
cannot infer T
编译错误(参见 Go playground 代码,here)。在我看来,
a
上的类型参数设置为
int
,因此
B
上的类型参数也应设置为
int
。我可以改为调用
NewB[int]()
,但这对我来说似乎过于冗长。为什么会这样?

go generics type-inference
1个回答
1
投票

这是“为什么编译器不能根据返回类型的使用方式推断类型参数?”的变体。答案:因为这不是类型推断的工作方式,从 Go 1.20 开始。

类型推断适用于:

  • 类型参数列表
  • 用已知类型参数初始化的替换映射 M,如果有的话
  • 一个(可能为空)普通函数参数列表(仅在函数调用的情况下)

NewB()
有类型参数列表吗?不,你在调用它时没有指定类型参数。

是否有其他已知类型参数可以用来推断其他类型参数?不,您根本没有提供任何类型参数。请注意,这种情况适用于您提供部分类型参数的函数调用,例如:

func foo[T any, U *T]() {}

在上面你可以只提供

T
,例如
float64
,编译器将用
T -> float64
构造一个替换映射,然后推断出
U -> 
*float64`

最后,有普通函数参数列表吗?不。

NewB
无效。

就是这样。编译器不会根据函数返回类型的使用方式推断类型参数。

© www.soinside.com 2019 - 2024. All rights reserved.