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.