无法在类型参数值上使用类型断言。

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

Cannot use type assertion on type parameter value

问题

我们无法在泛型类型的变量上使用类型断言。这看起来非常奇怪,因为它在interface{}上是允许的,但在受interface{}约束的泛型上却不允许。想知道是否有任何解决方法?

// 这个可以工作
func isInt(x interface{}) bool {
	_, ok := x.(int)
	return ok;
}

// 编译错误
// 无效操作:无法在受interface{}约束的类型参数值x(类型为T的变量)上使用类型断言
func isInt2[T interface{}](x T) bool {
	_, ok := x.(int)
	return ok;
}
英文:

We can't use type assertions on generic typed variables. This seems like really strange behavior considering it's allowed by interface{}, but not by a generic constrained by interface{}. Wondering if there are any work arounds?

// This works
func isInt(x interface{}) bool {
	_, ok := x.(int)
	return ok;
}

// Compile Error
// invalid operation: cannot use type assertion on type parameter 
// value x (variable of type T constrained by interface{})
func isInt2[T interface{}](x T) bool {
	_, ok := x.(int)
	return ok;
}

答案1

得分: 58

你可以只对接口值进行类型断言。所以你必须先将 x 转换为有效的接口类型,即 any / interface{}

func isInt[T any](x T) (ok bool) {
    _, ok = any(x).(int) // 先转换,然后断言
    return
}

那么为什么这个代码段无法编译通过呢?你可以在这里查看 示例

_, ok = x.(int)   // ... cannot use type assertion on type parameter value ...

x 的类型 T 是一个类型参数,而不是一个接口类型。它只受到接口的约束。Go(修订版 1.18)语言规范明确指出,在 类型断言 中不允许使用类型参数:

对于一个表达式 x 的类型是接口类型,但不是类型参数,以及一个类型 Tx.(T) 的表示被称为类型断言。

此外,根据 泛型教程 中的解释,参数类型需要在编译时解析的原因是:

虽然类型参数的约束通常表示一组类型,但在编译时,类型参数代表的是单个类型,即调用代码提供的类型参数。如果类型参数的约束不允许使用类型参数的类型参数,则代码将无法编译通过。

英文:

tl;dr

You can perform a type assertion only on interface values. So you must convert x to a valid interface type first, any / interface{} in this case:

func isInt[T any](x T) (ok bool) {

    _, ok = any(x).(int) // convert, then assert
    return
}

So why does this fail to compile?

_, ok = x.(int)   // ... cannot use type assertion on type parameter value ...

x's type T is a type parameter, not an interface. It is only constrained by an interface. The Go (revised 1.18) language spec explicitly states type parameters are not allowed in a type assertion:

> For an expression x of interface type, but not a type
> parameter
, and a type T ... the notation x.(T) is called a type assertion.


Also from from the generics tutorial on why parameter types need to be resolved at compile-time:

> While a type parameter’s constraint typically represents a set of
> types, at compile time the type parameter stands for a single type
> the type provided as a type argument by the calling code. If the type
> argument’s type isn’t allowed by the type parameter’s constraint, the
> code won’t compile.

huangapple
  • 本文由 发表于 2022年3月23日 21:21:34
  • 转载请务必保留本文链接:https://go.coder-hub.com/71587996.html
匿名

发表评论

匿名网友

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

确定