为了账号安全,请及时绑定邮箱和手机立即绑定

syscall.Sockaddr 类型断言

syscall.Sockaddr 类型断言

Go
慕姐4208626 2021-08-16 15:41:48
我正在打开一个 Linux 数据包套接字并尝试将接收到的数据包读入一个结构:type msg struct {    n, oobn, flags int    p, oob []byte    from syscall.Sockaddr}socket, err := syscall.Socket(AF_PACKET, SOCK_RAW, ETH_P_ALL)pkt := new(msg)pkt.p = make([]byte, 1500)pkt.oob = make([]byte, 1500)pkt.n, pkt.oobn, pkt.flags, pkt.from, _ = syscall.Recvmsg(socket, pkt.p, pkt.oob, 0)根据文档(http://golang.org/pkg/syscall/#Recvmsg)Recvmsg()返回 msghdr 作为 asyscall.Sockaddr并且我上面概述的代码片段有效。打印出pkt.fromstruct成员,我可以看到Sockaddr界面中的值:fmt.Printf("%+v\n", pkt.from)>>> &{Protocol:8 Ifindex:3 Hatype:1 Pkttype:0 Halen:6 Addr:[0 0 36 205 126 213 0 0] raw:{Family:0 Protocol:0 Ifindex:0 Hatype:0 Pkttype:0 Halen:0 Addr:[0 0 0 0 0 0 0 0]}}但是,如果我尝试访问它们,则会收到错误消息:fmt.Println(pkt.from.Ifindex)>>> pkt.from.Ifindex undefined (type syscall.Sockaddr has no field or method Ifindex)通过reflect.TypeOf(pkt.from)我发现它是类型*syscall.SockaddrLinklayer. 尝试将我的msgstruct 成员更改为该类型时Recvmsg尝试执行分配失败,因为它不是 type syscall.Sockaddr。我能够使用类型断言:bar := pkt.from.(*syscall.SockaddrLinklayer)fmt.Println(bar.Ifindex)>>> 2我对 Go 很陌生;这是我的第一个静态类型语言,所以我不明白Recvmsgfunc 是如何需要asyscall.Sockaddr 但返回 a 的*syscall.SockaddrLinklayer?我显然错过了一些非常基本的东西。另外,使用类型断言是正确的方法吗?感觉不太对劲……但我真的没有资格做出这样的判断!
查看完整描述

1 回答

?
拉风的咖菲猫

TA贡献1995条经验 获得超2个赞

Sockaddr 是一个接口,因此Recvmsg可以返回满足该接口的不同类型。


有关接口的更多详细信息,请查看Effective Go。


您应该检查断言是否有效,以免最终出现运行时错误,例如:


bar, ok := pkt.from.(*syscall.SockaddrLinklayer) 

if !ok {

    //log error and break out of the loop

}

stuffWith(bar)


查看完整回答
反对 回复 2021-08-16
  • 1 回答
  • 0 关注
  • 172 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信