代码之家  ›  专栏  ›  技术社区  ›  Woody1193 Nimmi Rashinika

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

  •  0
  • Woody1193 Nimmi Rashinika  · 技术社区  · 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游乐场代码, here ).在我看来,上的type参数 a 设置为 int 所以上的类型参数 B 也应设置为 int 。我可以打电话 NewB[int]() 相反,但这在我看来过于冗长。为什么会发生这种情况?

    1 回复  |  直到 1 年前
        1
  •  2
  •   blackgreen    1 年前

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

    Type inference 适用于:

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

    如果您逐一检查这些规则:

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

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

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

      在以上内容中,您只能提供 T ,例如。 float64 ,编译器将使用 T -> float64 然后推断 U -> *float64

    • 最后,是否有一个普通函数参数的列表?不 NewB 是无效的。

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

    在撰写本报告时,正在讨论的相关提案如下: