猿问

类型断言和接口

为什么第一个示例失败,但第二个成功?


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


示例 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}


倚天杖
浏览 181回答 2
2回答

慕仙森

问题是你没有传递 a Packet,你传递的map[string]interface{}是 a ,就 Go 而言,这是一种完全不同的类型。如果您使用pack := make(Packet)or pack := Packet{},它将按预期工作。

至尊宝的传说

到目前为止的答案和评论是误解,混淆,或者至少在类型断言和类型转换之间的区别中刷了很多细节。语法thing.(AType)是类型断言。它将在运行时进行评估。何时成功(即ok == true)的标准可以归结为两种情况:thing从字面上看是 type AType。不是像您的Packet.AType是接口,thing满足接口。在所有其他情况下,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{}
随时随地看视频慕课网APP

相关分类

Go
我要回答