无法在Golang中解析icmp消息

I'm a newb with Golang and trying to do what seems like a very simple task -- sending a ping with some text in it and reading that text back when I get a reply, but I'm running into some things I don't understand. I've built a ping like this:

 ping := icmp.Message{
    Type: ipv4.ICMPTypeEcho,
    Code: 0,
    Body: &icmp.Echo{
        ID: os.Getpid() & 0xffff,
        Seq: 1,
        Data: []byte("Hello"),
    },
}

Here's the socket read part for context:

buf := make([]byte, 1500)
_, peer, err := c.ReadFrom(buf)
message, err := icmp.ParseMessage(1, buf)

Here's my failed effort to get my data back out of the message body:

body := message.Body;
fmt.Println("body.ID ", body.ID)
fmt.Println("body.Seq ", body.Seq)
fmt.Println("body.Data ", string(body.Data))

Go is not happy at build time:

./ping.go:86: body.ID undefined (type icmp.MessageBody has no field or method ID)
./ping.go:87: body.Seq undefined (type icmp.MessageBody has no field or method Seq)
./ping.go:88: body.Data undefined (type icmp.MessageBody has no field or method Data)

This code, however, which is adapted from this awesome project, works just swell:

switch body := message.Body.(type) {
  case *icmp.Echo:
    fmt.Println("body.ID ", body.ID)
    fmt.Println("body.Seq ", body.Seq)
    fmt.Println("body.Data ", string(body.Data))
  default:
    fmt.Println("not a *icmp.Echo")
}

Go is perfectly happy to compile and run this code. Can someone tell me why the code in the type switch works fine, but the first example results in compile errors. Thank you!

message.Body is a MessageBody (https://godoc.org/golang.org/x/net/icmp#MessageBody) which is an interface type. If you want the underlying type you need to cast it. One way to do that would be to say

body := message.Body.(*icmp.Echo)
...

This would likely work for you, but if the MessageBody is NOT an icmp.Echo pointer then it will be a panic.

The type switch makes sure there is no panic.

You could also do

if body, ok := message.Body.(*icmp.Echo); ok {
    // do something with Body as an *icmp.Echo type
}

to guard against the panic.