英文:
Convert struct to []byte with Go
问题
我有一个数据包结构,我希望将其序列化为二进制格式,以便通过网络发送。
有许多数据包结构,但我将以登录数据包作为示例:
login结构体 {
seq uint8
id uint16
username [16]string
password [16]string
unknown1 [16]byte
}
我在某个地方读到,对于非固定大小的结构体,不能使用binary.Write
。但我相信我的结构体是固定大小的(如果我错了,请纠正我,我可能非常错误)。
现在使用以下代码:
var buf bytes.Buffer
x := login{
seq: 2,
id: 1,
username: [16]string{"username"},
password: [16]string{"password"},
}
err := binary.Write(&buf, binary.LittleEndian, x)
if err != nil {
log.Fatalln(err)
}
这给我报错:binary.Write: invalid type main.login
现在,有没有办法解决这个问题?有没有其他方法?就像在C中可以使用结构体并通过网络发送一样。
英文:
I have a packet structure and I wish to serialize it into binary so I can send it through the wire.
There are many packet structures but I'll give the login packet as an example:
login struct {
seq uint8
id uint16
username [16]string
password [16]string
unknown1 [16]byte
}
I've read somewhere that you can't use binary.Write
for non-fixed size structures. But I believe my structure is fixed size (correct me if I'm wrong, I could be very wrong).
Now using this code:
var buf bytes.Buffer
x := login{
seq: 2,
id: 1,
username: [16]string{"username"},
password: [16]string{"password"},
}
err := binary.Write(&buf, binary.LittleEndian, x)
if err != nil {
log.Fatalln(err)
}
Gives me the error: binary.Write: invalid type main.login
Now, is there a way to fix this? Is there an alternative approach? Much like how you can use structs in C and send it through the network.
答案1
得分: 5
你的代码中有两个错误。首先,你的结构体字段应该是可导出的,这样encoding/binary
才能看到它。
其次,[16]string
表示一个包含16个字符串的数组,而不是一个16字节的字符串。所以你的结构体应该像这样:
type login struct {
Seq uint8
ID uint16
Username [16]byte
Password [16]byte
Unknown1 [16]byte
}
然后它就可以工作了:https://play.golang.org/p/Nq8fRqgkcp。
英文:
You have two errors in your code. Firstly, your struct fields should be exported for encoding/binary
to see it.
Secondly, [16]string
means an array of 16 strings, not a 16-byte string. So your struct should look like this:
type login struct {
Seq uint8
ID uint16
Username [16]byte
Password [16]byte
Unknown1 [16]byte
}
Then it works: https://play.golang.org/p/Nq8fRqgkcp.
答案2
得分: 5
你可以使用unsafe
包来实现这个。
type test struct {
a int
s string
}
v1 := test{
a: 5,
s: "sdaf",
}
fmt.Printf("v1: %#v\n", v1)
b := *(*[unsafe.Sizeof(v1)]byte)(unsafe.Pointer(&v1))
fmt.Printf("bytes: %#v\n", b)
v2 := *(*test)(unsafe.Pointer(&b))
fmt.Printf("v2: %#v\n", v2)
请注意,unsafe
包提供了一种绕过Go语言类型系统的方法,因此使用时需要特别小心。
英文:
You can do that using the unsafe
package.
type test struct {
a int
s string
}
v1 := test{
a: 5,
s: "sdaf",
}
fmt.Printf("v1: %#v\n", v1)
b := *(*[unsafe.Sizeof(v1)]byte)(unsafe.Pointer(&v1))
fmt.Printf("bytes: %#v\n", b)
v2 := *(*test)(unsafe.Pointer(&b))
fmt.Printf("v2: %#v\n", v2)
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论