英文:
What's a compact way of casting a struct into a byte slice in Go?
问题
在编写网络代码时,我们经常需要从字节片段中填充结构体,以便以对象的形式访问数据。
让我们以这个结构体为例:
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 {
// 处理错误
}
但是:
- 它使用了
unsafe
包 - 每次转换都需要大约 7 行代码(如果有数百个不同的数据包怎么办)
- 不能简单地打包到一个
Cast(*struct, data)
函数中 - 无法控制结构体的填充方式,如果 Go 的编译器决定在网络的某一端在成员之间添加额外的字节会怎么样?
- 如果我没记错的话,binary.Read 会执行数据拷贝(这不一定是缺点)
在 C 语言中,我们只需在网络的两端使用 #pragma pack(1)
,并达成一致的字节序,最后使用 PACKETHEAD* pkt = (PACKETHEAD*)dataptr;
。
我们如何在 Go 中实现相同的功能呢?
祝您有愉快的一天,
Kris
英文:
When writing network code we often find ourselves populating structs from byte slices to access the data in form of an object.
Let's take this struct
type PACKETHEAD struct {
Type uint16
Size uint16
Hash uint32
}
and a byte slice that has been somehow populated with data
data := make([]byte, 1024)
My solution would be to
var pkthead PACKETHEAD
pktsiz := unsafe.Sizeof(pkthead)
pktbuf := bytes.NewReader(buf[:pktsiz])
err = binary.Read(pktbuf, binary.BigEndian, &pkthead)
if err != nil {
// handle it
}
But
-
It uses
unsafe
-
Requires ~7 lines of code for every cast (what if we had hundreds of different packets)
-
Can't be trivially packed into a
Cast(*struct, data)
function -
No control over struct padding, what If go's compiler decides to add extra bytes in between members on one end of a network?
-
binary.Read performs a data copy if I'm not mistaken (this isn't necessarily a con)
In C one would just #pragma pack(1)
on both network ends, agree on one type of endianess
and finally PACKETHEAD* pkt = (PACKETHEAD*)dataptr;
How can we achieve the same thing with Go?
Have a nice day,
Kris
答案1
得分: 3
gopack
是一个我(和其他人)编写的用于在Go语言中支持位打包的库。注意:它在底层使用了不安全的操作,如果这是一个问题的话。
英文:
Shameless plug for gopack
, a library I (and others) wrote to support bitpacking in Go. Note: it uses unsafe operations under the hood, if that's a problem.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论