【发布时间】:2016-05-30 01:32:04
【问题描述】:
在编写网络代码时,我们经常发现自己从字节切片填充结构以访问对象形式的数据。
让我们来看看这个结构
type PACKETHEAD struct {
Type uint16
Size uint16
Hash uint32
}
以及以某种方式填充了数据的字节切片
data := make([]byte, 1024)
我的解决方案是
var pkthead PACKETHEAD
pktsiz := unsafe.Sizeof(pkthead)
pktbuf := bytes.NewReader(buf[:pktsiz])
err = binary.Read(pktbuf, binary.BigEndian, &pkthead)
if err != nil {
// handle it
}
但是
它使用
unsafe每次转换需要大约 7 行代码(如果我们有数百个不同的数据包会怎样)
不能简单地打包到
Cast(*struct, data)函数中无法控制结构填充,如果 go 的编译器决定在网络一端的成员之间添加额外字节怎么办?
binary.Read 如果我没记错的话会执行数据复制(这不一定是骗局)
在 C 语言中,网络两端只需要#pragma pack(1),就一种字节序达成一致
最后是PACKETHEAD* pkt = (PACKETHEAD*)dataptr;
我们如何用 Go 实现同样的目标?
祝你有美好的一天, 克里斯
【问题讨论】:
-
@Denzel 这不是重复的,您发布的链接中的答案实际上是我的建议。
-
没错,这是正确的方法。以 C 方式执行此操作会破坏 Go 的类型安全,因此不提供。
-
@Denzel 好吧,我希望这不是唯一的方法。这就是我问这个问题的原因。
-
使用像 protobuf 这样的序列化器怎么样?这似乎更安全。
标签: networking go struct casting padding