键入断言和接口

时间:2016-05-08 22:07:05

标签: go interface

为什么第一个例子失败了,但第二个例子顺利?

这种断言的正确方法是什么?

示例1 https://play.golang.org/p/4LRGQLdGPB

// example 1
type Packet map[string]interface{}

func get(pack interface{}) {
    if packet, ok := pack.(Packet); !ok {
        fmt.Printf("error: %#v, %#v\n", pack, packet)
    }
}

func main() {
    pack := make(map[string]interface{})
    pack["qwe"] = 123
    get(pack)
}

// error: map[string]interface {}{"qwe":123}, main.Packet(nil)

示例2 https://play.golang.org/p/Pd9jvvNrq5

// example 2
type Packet map[string]interface{}

func get(pack interface{}) {
    var p Packet
    if packet, ok := pack.(map[string]interface{}); !ok {
        fmt.Printf("%#v, %#v\n", pack, packet)
    } else {
        p = packet
    }
    fmt.Printf("%#v\n", p)
}

func main() {
    pack := make(map[string]interface{})
    pack["qwe"] = 123
    get(pack)
}

// main.Packet{"qwe":123}

2 个答案:

答案 0 :(得分:1)

问题是你没有传递Packet,你传递的是map[string]interface{},就Go而言,这是一种完全不同的类型。

如果您使用pack := make(Packet)pack := Packet{},它将按预期工作。

playground

答案 1 :(得分:0)

到目前为止,答案和评论都是误解,混淆,或至少在type assertiontype conversion之间的细微差别。

语法thing.(AType)是一种类型断言。它将在运行时评估。何时成功(即ok == true)的标准可归结为两种情况:

  1. thing字面上是AType类型。不是像Packet那样重新申报的类型。
  2. AType是一个接口,thing满足接口。
  3. 在所有其他情况下,ok将为false(或者如果您使用单值版本foo := bar.(Baz)foo将是适当的零值。)

    语法AType(thing)是类型转换。它将在编译时进行评估。类型转换要求AType的内存结构和thing类型相同。

    因此,在您的示例中,类型断言packet, ok := pack.(Packet)会导致ok == false,因为Packet是非接口类型,packet不是字面上的那种类型,它的类型为map[string]interface

    但是,您可以进行类型转换Packet(pack),因为类型Packet和变量pack具有相同的基础内存结构map[string]interface{}