一尘不染

如何在Go中强制转换为类型别名?

go

看到 这个操场片段

相关代码:

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.")
}

通过显式声明类型,第一个类型转换起作用。但是,第二次引发恐慌。为什么?是否有一种干净的方法可以转换为更长的功能签名?


阅读 370

收藏
2020-07-02

共1个答案

一尘不染

tl; dr

对于类型断言(您使用的类型),仅实际类型很重要。因此somethingFuncy,仅等于somethingFuncy和不等于func(int) bool

说明

首先,这与铸造无关。进行中没有强制转换。有类型断言类型转换

您正在处理类型断言,并假设与类型 转换 具有相同的条件。在阅读您的问题时,我犯了同样的错误,但实际上在行为上存在巨大差异。

假设您有两种类型,比如inttype MyInt int。这些都是可转换的,因为它们都共享相同的基础类型(转换规则之一),因此可以正常工作(播放):

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

现在,假设a不是类型int而是interface{}play)类型:

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

编译器会告诉您:

无法将类型接口{}转换为MyInt类型:需要类型断言

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

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

现在,我们遇到的问题与您的问题相同。此断言由于以下错误而失败:

恐慌:接口转换:接口是int而不是main.MyInt

规范的类型断言部分说明了这种情况的原因:

对于接口类型和类型的表达式x T,主表达式x.(T) 断言x不是,nil并且其中存储的值x是类型T。该符号
x.(T)称为类型声明。 更确切地说,如果T不是接口类型,x.(T)则断言的动态类型x与type相同T

因此int必须与相同MyInt类型标识规则声明(除其他规则外):

如果两个命名类型的类型名称源自同一TypeSpec,则它们是相同的。

作为intMyInt有不同的声明(TypeSpecs)他们不是平等的,断言失败。当对断言aint,断言起作用。因此,您正在做的事情是不可能的。

奖金:

实际检查在此代码中进行该代码仅按预期检查两种类型是否相同。

2020-07-02