我可以将int转换为float64,如下所示:
var a int = 10
var b float64 = float64(a)
关于类型断言,Effective Go声明:'类型必须是接口持有的具体类型,或者是值可以转换为的第二种接口类型。'
考虑到这一点,为什么以下失败:
func foo(a interface{}) {
fmt.Println(a.(float64))
}
func main() {
var a int = 10
foo(a)
}
这会导致panic: interface conversion: interface is int, not float64
。
请注意,Go Spec说:
'对于接口类型的表达式x和类型T,主表达式
x.(T)
断言x不是nil,存储在x中的值是T的类型。'
哪个与Effective Go语句相矛盾,但似乎更符合我所看到的。
答案 0 :(得分:9)
This sentence似乎确实令人困惑。看起来作者当时正在思考结构。
The chapter on assertions in the specification更加清晰:
对于接口类型的表达式x和类型T,表示主要的 表达
x。(T)断言x不是nil,而x中存储的值是 类型T.符号x。(T)称为类型断言。
更准确地说,如果T不是接口类型,则x。(T)断言 动态类型x与类型T相同。在这种情况下,T必须 实现x的(接口)类型;否则类型断言是 因为x不可能存储类型T的值,所以无效 T是接口类型,x。(T)断言x的动态类型 实现接口T。
事实you can convert your int to a float(反过来)并不意味着你可以断言他们是同一类型。
答案 1 :(得分:8)
类型必须是接口持有的具体类型,或者第二个接口类型,可以将值转换为
这基本上解释了following:
package main
import "fmt"
type Stringer interface {
String()
}
type Byter interface {
Bytes()
}
type Stringbyter interface {
Stringer
Byter
}
type Polymorphic float64
func (p *Polymorphic) String() {}
func (p *Polymorphic) Bytes() {}
func main() {
i := interface{}(new(Polymorphic))
if _, ok := i.(Stringer); ok {
fmt.Println("i can be asserted to Stringer")
}
if _, ok := i.(Byter); ok {
fmt.Println("i can be asserted to Byter")
}
if _, ok := i.(Stringbyter); ok {
fmt.Println("i can be asserted to Stringbyter")
}
if _, ok := i.(*Polymorphic); ok {
fmt.Println("i can be asserted to *Polymorphic")
}
if _, ok := i.(int); ok {
fmt.Println("i can be asserted to int") // Never runs
}
}
对int
的断言失败,因为它是具体类型(与接口类型相反),而不是*Polymorphic
本身。
答案 2 :(得分:0)
您只能从接口类型键入断言到基础类型。在这种情况下int
。然后,您使用从int
到float64