如何投射到Go中的类型别名? [英] How to cast to a type alias in Go?

查看:195
本文介绍了如何投射到Go中的类型别名?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

请参阅 此运动场片段



相关代码:

 键入somethingFuncy func(int)bool 

func funcy int)bool {
return i%2 == 0
}

var a interface {} = funcy

func main(){

_ = a。(func(int)bool)// Works

fmt.Println(Awesome - 显然指定func签名工作。 b
_ = a。(somethingFuncy)// Panics

fmt.Println(Darn - 不会在这里,但是somethingFuncy是和func(int)bool一样的签名。 )
}

第一次强制转换通过显式声明类型。但第二次铸造恐慌。为什么?

解决方案

tl; dr



对于类型断言(你使用),只有实际类型很重要。所以 somethingFuncy 只等于 somethingFuncy ,而不是 func(int)bool



说明



首先,这与转换无关。没有投掷。
类型断言 type conversions



您正在处理类型断言,对于类型转化,持有
。我在读取你的问题时犯了同样的错误,但实际上行为有很大的不同。



假设你有两种类型, int 键入MyInt int 。这些是可转换的,因为它们两个
共享相同的底层类型(一个转换规则),所以这工作( play ):

  var a int = 10 
var b MyInt = MyInt(a)

现在,假设 a int 但类型 interface {} play ):

  var a interface {} = int 10)
var b MyInt = MyInt(a)

编译器会告诉你: / p>

b
$ b

现在我们不再进行转换,而是断言。我们需要这样做(播放):

  var a interface {} = int(10)
var b MyInt = a(MyInt)

现在我们有同样的问题。这种断言失败,出现这种恐慌:


panic:interface conversion:interface is int,not main.MyInt


原因在类型声明中说明部分


对于接口类型的表达式x和类型 T ,主表达式 x。(T)
断言 x code> nil
,并且 x 中存储的值的类型为 T 。符号
x。(T)被称为类型断言。
更精确地说,如果 T 不是接口类型, x。(T) x 的动态
类型与 T
类型相同。


因此 int 必须与 MyInt 类型身份的规则说明
(其他规则中):


如果两个命名类型的类型名称来源于同一个TypeSpec,它们是完全相同的。


As int MyInt 有不同的声明( TypeSpecs ),它们不等于
,断言失败。当你声明 a int 时,断言工作。
所以你在做什么是不可能的。



奖金:



此代码中的 ,它只是检查两个类型是否都是
,如预期的那样。


See this playground snippet.

Relevant code:

type somethingFuncy func(int) bool

func funcy(i int) bool {
    return i%2 == 0
}

var a interface{} = funcy

func main() {

    _ = a.(func(int) bool)  // Works

    fmt.Println("Awesome -- apparently, literally specifying the func signature works.")

    _ = a.(somethingFuncy)  // Panics

    fmt.Println("Darn -- doesn't get here. But somethingFuncy is the same signature as func(int) bool.")
}

The first cast works, by explicitly declaring the type. But the second cast panics. Why? Is there a clean way to cast to a longer func signature?

解决方案

tl;dr

For type assertions (which you use) only the actual type matters. So somethingFuncy is only equal to somethingFuncy and not to func(int) bool.

Explanation

To start with, this has nothing to do with casting. There is no casting in go. There are type assertions and type conversions.

You're dealing with a type assertion and are assuming that the same conditions hold as for type conversions. I made the same mistake while reading your question but actually there is a huge difference in behaviour.

Suppose you have two types, say int and type MyInt int. These are convertible as they both share the same underlying type (one of the conversion rules), so this works (play):

var a int = 10
var b MyInt = MyInt(a)

Now, suppose a is not of type int but of type interface{} (play):

var a interface{} = int(10)
var b MyInt = MyInt(a)

The compiler will tell you:

cannot convert a (type interface {}) to type MyInt: need type assertion

So now we're not doing conversions anymore but assertions. We need to do this (play):

var a interface{} = int(10)
var b MyInt = a.(MyInt)

Now we have the same problem as in your question. This assertion fails with this panic:

panic: interface conversion: interface is int, not main.MyInt

The reason for this is stated in the type assertions section of the spec:

For an expression x of interface type and a type T, the primary expression x.(T) asserts that x is not nil and that the value stored in x is of type T. The notation x.(T) is called a type assertion. More precisely, if T is not an interface type, x.(T) asserts that the dynamic type of x is identical to the type T.

So int must be identical to MyInt. The rules of type identity state that (amongst other rules):

Two named types are identical if their type names originate in the same TypeSpec.

As int and MyInt have different declarations (TypeSpecs) they're not equal and the assertion fails. When you assert a to int, the assertion works. So what you're doing is not possible.

Bonus:

The actual check happens in this code, which simply checks if both types are the same, as expected.

这篇关于如何投射到Go中的类型别名?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆