去类型断言转换

时间:2013-05-30 13:21:35

标签: go

我可以将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语句相矛盾,但似乎更符合我所看到的。

3 个答案:

答案 0 :(得分:9)

在Effective Go中,

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。然后,您使用从intfloat64

的类型转换