看到这个游乐场片段.
相关代码:
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.")
}
Run Code Online (Sandbox Code Playgroud)
第一个演员通过明确声明类型来工作.但第二次演员恐慌.为什么?是否有一种干净的方式来转换为更长的功能签名?
nem*_*emo 58
对于类型断言(您使用),只有实际类型很重要.所以somethingFuncy
只等于somethingFuncy
而不是func(int) bool
.
您正在处理类型断言,并假设条件转换的条件相同.我在阅读你的问题时犯了同样的错误,但实际上行为存在巨大差异.
假设你有两种类型,比如说int
和type MyInt int
.这些是可转换的,因为它们共享相同的底层类型(转换规则之一),所以这适用(播放):
var a int = 10
var b MyInt = MyInt(a)
Run Code Online (Sandbox Code Playgroud)
现在,假设a
不是类型int
而是类型interface{}
(播放):
var a interface{} = int(10)
var b MyInt = MyInt(a)
Run Code Online (Sandbox Code Playgroud)
编译器会告诉你:
无法将(类型接口{})转换为MyInt类型:需要类型断言
所以现在我们不再做转换了,而是断言.我们需要这样做(玩):
var a interface{} = int(10)
var b MyInt = a.(MyInt)
Run Code Online (Sandbox Code Playgroud)
现在我们遇到与您的问题相同的问题.这种说法因恐慌而失败:
恐慌:界面转换:界面是int,而不是main.MyInt
原因在规范的类型断言部分中说明:
对于接口类型和类型的表达式x
T
,主表达式x.(T)
断言x
不是,nil
并且存储的值x
是类型T
.该表示法x.(T)
称为类型断言. 更确切地说,如果T
不是接口类型,x.(T)
则断言动态类型x
与类型相同T
.
所以int
必须相同MyInt
.类型标识的规则规定(以及其他规则):
如果两个命名类型的类型名称源自相同的TypeSpec,则它们是相同的.
由于int
并且MyInt
具有不同的声明(TypeSpecs),它们不相等并且断言失败.断言a
时int
,断言有效.所以你正在做的事情是不可能的.
实际检查发生在此代码中,它只是检查两种类型是否与预期相同.
aga*_*eld 16
使用Go 1.9中的类型断言,您只需添加=
定义类型的位置即可.
type somethingFuncy = func(int) bool
Run Code Online (Sandbox Code Playgroud)
这告诉编译器这somethingFuncy
是一个替代名称func(int) bool
.
只是为了完成nemo的精彩答案,请注意,虽然您无法直接从interface{}
给定动态类型(例如int
)的接口(例如)跳转到另一种类型(例如type MyInt int
),但您可以一个接一个地执行这两个步骤:
请注意,由于底层类型顾名思义是动态的,因此测试类型断言是成功还是失败是个好主意.另一方面,类型转换的正确性由编译器强制执行.
这是您的游乐场片段略有修改:http://play.golang.org/p/FZv06Zf7xi