9

我可以像这样将 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 规范说:

'对于接口类型的表达式 x 和类型 T,主表达式

x.(T)

断言 x 不是 nil 并且存储在 x 中的值是 T 类型。

这确实与 Effective Go 声明相矛盾,但似乎更符合我所看到的。

4

3 回答 3

9

类型必须是接口持有的具体类型,或者是值可以转换为的第二个接口类型

这基本上解释了以下内容

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

于 2013-05-30T21:42:00.640 回答
9

Effective Go 中的这句话似乎确实令人困惑。看起来作者当时正在考虑结构。

规范中关于断言的章节更加清晰:

对于接口类型的表达式 x 和类型 T,主表达式

x.(T) 断言 x 不是 nil 并且存储在 x 中的值是 T 类型。符号 x.(T) 称为类型断言。

更准确地说,如果 T 不是接口类型,则 x.(T) 断言 x 的动态类型与类型 T 相同。在这种情况下,T 必须实现 x 的(接口)类型;否则类型断言无效,因为 x 不可能存储类型 T 的值。如果 T 是接口类型,x.(T) 断言 x 的动态类型实现接口 T。

您可以将 int 转换为 float (反之亦然)这一事实并不意味着您可以断言它们是相同的类型。

于 2013-05-30T13:28:42.630 回答
0

您只能从接口类型到基础类型键入断言。在这种情况下int。然后你使用类型转换 from inttofloat64

于 2014-05-30T18:29:36.280 回答