将结构体转换为字节切片([]byte)的方法在Go语言中如下所示:

huangapple go评论71阅读模式
英文:

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)

huangapple
  • 本文由 发表于 2017年2月7日 00:07:14
  • 转载请务必保留本文链接:https://go.coder-hub.com/42072214.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定