为什么Go函数不能返回具有约束类型参数的类型?

huangapple go评论107阅读模式
英文:

Why can't Go functions return a type with a constrained type parameter?

问题

在尝试在Go中在编译时强制执行有效状态转换的问题上,我遇到了一个限制:函数不能返回具有非具体类型参数的通用类型。在这个问题中有详细说明。以下是一个无法构建的最小可复现示例(Go playground链接):

type MyStruct[T any] struct {
	MyField T
}

func returnConstrainedGeneric[T any]() MyStruct[T] {
    return MyStruct[int]{
		MyField: 1,
	}
}

编译器返回错误信息:cannot use MyStruct[int]{…} (value of type MyStruct[int]) as MyStruct[T] value in return statement

链接的问题给出了以下解释:
> 错误发生的原因是涉及类型参数的操作(包括赋值和返回)必须对其类型集中的所有类型都有效。

它提供了一些解决方法,包括类型断言,但我对为什么存在这种限制感到好奇。从直觉上讲,在我的示例中,我期望从returnConstrainedGeneric()返回类型为MyStruct[int]的值是有效的,因为int满足any的类型约束。我期望returnConstrainedGeneric()的调用者不知道返回的值的类型是MyStruct[int],它只知道它是一个满足any约束的MyStruct[T]类型。在我的推理中,我漏掉了什么?这是Go如何实现泛型/类型约束的一个基本问题,还是Go编译器当前实现的问题,或者其他原因导致的?

英文:

While working on a problem with trying to enforce valid state transitions at compile time in Go, I've run into the limitation that a function can't return a generic type with a non-concrete type parameter, as outlined in this question. MRE that fails to build (Go playground link):

type MyStruct[T any] struct {
	MyField T
}

func returnConstrainedGeneric[T any]() MyStruct[T] {
    return MyStruct[int]{
		MyField: 1,
	}
}

The compiler returns the error cannot use MyStruct[int]{…} (value of type MyStruct[int]) as MyStruct[T] value in return statement.

The linked question gives this reasoning:
> The error occurs because operations that involve a type parameter (including assignments and returns) must be valid for all types in its type set.

It outlines a couple of workarounds including type assertions, but I'm curious about why this restriction is in place. Naively, in my example, I would expect that's it valid to return a value of type MyStruct[int] from returnConstrainedGeneric(), because int satisfies the type constraint of any. I'd expect that a caller of returnConstrainedGeneric() wouldn't know that the returned value was of type MyStruct[int], it'd just know that it's a MyStruct[T] where T meets the any constraint. What am I missing in my reasoning? Is this a fundamental issue with how Go implements generics/type constraints, an issue with the current implementation of the Go compiler, or something else?

答案1

得分: 4

这是无效的,因为语法意味着:

x:=returnConstrainedGeneric[string]()
// x 是 MyStruct[string]

但你试图返回一个 MyStruct[int]

你推理的缺陷在于你在实例化函数时指定了返回类型。函数不能返回满足 any 约束的类型,它返回的是实例化时的类型。换句话说,函数实例化时的 T 必须与 MyStruct[T] 中的 T 相同。

如果你总是返回 MyStruct[int],请声明为:

func returnConstrainedGeneric[T any]() MyStruct[int] {...}

或者,如果函数根本不使用 T

func returnConstrainedGeneric() MyStruct[int] {...}
英文:

This is invalid because the syntax means that

x:=returnConstrainedGeneric[string]()
// x is MyStruct[string]

but you are trying to return a MyStruct[int].

The flaw in your reasoning is that you specify the return type of the function when you instantiate it. The function cannot return a type that satisfies the any constraint, it returns the type that it is instantiated for. In other words, the T the function is instantiated has to be the same T in MyStruct[T].

If you always return MyStruct[int], declare it as such:

func returnConstrainedGeneric[T any]() MyStruct[int] {...}

or, if the function doesn't use T at all:

func returnConstrainedGeneric() MyStruct[int] {...}

huangapple
  • 本文由 发表于 2023年7月17日 09:29:50
  • 转载请务必保留本文链接:https://go.coder-hub.com/76701039.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定