类型断言和接口

Why first example fails, but second goes well?

What is correct way to do such assertion?

example 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
", pack, packet)
    }
}

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

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

example 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
", pack, packet)
    } else {
        p = packet
    }
    fmt.Printf("%#v
", p)
}

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

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

The problem is you're not passing a Packet, you're passing a map[string]interface{}, which is a completely different type as far as Go is concerned.

If you use pack := make(Packet) or pack := Packet{}, it will work as intended.

playground

The answers and comments so far are misunderstanding, mixing up, or at least brushing over a lot of detail in the difference between a type assertion and a type conversion.

The syntax thing.(AType) is a type assertion. It will be evaluated at runtime. The criteria for when this will be successful (i.e. ok == true) can be boiled down to really 2 situations:

  1. thing is literally of type AType. Not a redeclared type like your Packet.
  2. AType is an interface and thing satisfies the interface.

In all other cases, ok will be false (or if you use the single value version foo := bar.(Baz), foo will be whatever the appropriate zero value is).

The syntax AType(thing) is a type conversion. It will be evaluated at compile time. A type conversion requires the in memory structure of AType and whatever type thing is, to be identical.

Therefore, in your example the type assertion, packet, ok := pack.(Packet) results in ok == false because Packet is a non-interface type, and packet is not literally of that type, it is of type map[string]interface.

However, you can do the type conversion Packet(pack), because the type Packet and the variable pack have the same underlying memory structure, map[string]interface{}