我是Golang的新手,尝试做看似非常简单的任务-发送ping命令,其中包含一些文本,并在收到回复时读回该文本,但是我遇到了一些我不知道的事情不明白。我建立了这样的ping:

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

这是上下文的套接字读取部分:
buf := make([]byte, 1500)
_, peer, err := c.ReadFrom(buf)
message, err := icmp.ParseMessage(1, buf)

这是我从数据正文中取回数据的失败尝试:
body := message.Body;
fmt.Println("body.ID ", body.ID)
fmt.Println("body.Seq ", body.Seq)
fmt.Println("body.Data ", string(body.Data))

Go在构建时并不高兴:
./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 awesome project改编而来的,只是膨胀了:
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非常乐意编译并运行此代码。有人可以告诉我为什么类型开关中的代码可以正常工作,但是第一个示例会导致编译错误。谢谢!

最佳答案

message.Body是接口(interface)类型的MessageBody(https://godoc.org/golang.org/x/net/icmp#MessageBody)。如果需要基础类型,则需要强制转换。一种方法是说

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

这可能会为您工作,但是如果MessageBody不是icmp.Echo指针,那么它将很 panic 。

类型开关可确保不会出现紧急情况。

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

防止 panic 。

关于go - 无法在Golang中解析icmp消息,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/38559074/

10-12 23:44