majidarif
majidarif

Reputation: 20025

Convert struct to []byte with Go

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.

Upvotes: 5

Views: 11548

Answers (2)

amenzhinsky
amenzhinsky

Reputation: 992

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)

Upvotes: 5

Ainar-G
Ainar-G

Reputation: 36229

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.

Upvotes: 5

Related Questions