看到 这个操场片段 。
相关代码:
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.") }
通过显式声明类型,第一个类型转换起作用。但是,第二次引发恐慌。为什么?是否有一种干净的方法可以转换为更长的功能签名?
对于类型断言(您使用的类型),仅实际类型很重要。因此somethingFuncy,仅等于somethingFuncy和不等于func(int) bool。
somethingFuncy
func(int) bool
首先,这与铸造无关。进行中没有强制转换。有类型断言和类型转换。
您正在处理类型断言,并假设与类型 转换 具有相同的条件。在阅读您的问题时,我犯了同样的错误,但实际上在行为上存在巨大差异。
假设您有两种类型,比如int和type MyInt int。这些都是可转换的,因为它们都共享相同的基础类型(转换规则之一),因此可以正常工作(播放):
int
type MyInt int
var a int = 10 var b MyInt = MyInt(a)
现在,假设a不是类型int而是interface{}(play)类型:
a
interface{}
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。
T
x.(T)
x
nil
因此int必须与相同MyInt。类型标识规则声明(除其他规则外):
MyInt
如果两个命名类型的类型名称源自同一TypeSpec,则它们是相同的。
作为int与MyInt有不同的声明(TypeSpecs)他们不是平等的,断言失败。当对断言a时int,断言起作用。因此,您正在做的事情是不可能的。
实际检查在此代码中进行,该代码仅按预期检查两种类型是否相同。