golang casting byte array to struct
Solution 1
According to http://golang.org/pkg/encoding/binary/#Read :
Data must be a pointer to a fixed-size value or a slice of fixed-size values.
So you can't use slice []byte
in your structure. But you can use fixed size array for it.
Like this:
package main
import (
"bytes"
"encoding/binary"
"fmt"
)
type T struct {
A int16
B int8
C [256]byte
}
func main() {
// Create a struct and write it.
t := T{A: 99, B: 10}
buf := &bytes.Buffer{}
err := binary.Write(buf, binary.BigEndian, t)
if err != nil {
panic(err)
}
fmt.Println(buf)
// Read into an empty struct.
t = T{}
err = binary.Read(buf, binary.BigEndian, &t)
if err != nil {
panic(err)
}
fmt.Printf("%d %d", t.A, t.B)
}
Solution 2
I think binpacker will be greate to handle this case:
package main
import (
"bytes"
"fmt"
"github.com/zhuangsirui/binpacker"
)
type T struct {
A uint16
B string
C []byte
}
func main() {
field1 := uint16(1)
field2 := "Hello World"
field3 := []byte("Hello World")
buffer := new(bytes.Buffer)
binpacker.NewPacker(buffer).
PushUint16(field1).
PushUint16(uint16(len(field2))).PushString(field2).
PushUint16(uint16(len(field3))).PushBytes(field3)
t := new(T)
unpacker := binpacker.NewUnpacker(buffer)
unpacker.FetchUint16(&t.A).StringWithUint16Perfix(&t.B).BytesWithUint16Perfix(&t.C)
fmt.Println(t)
}
user642318
Updated on July 05, 2020Comments
-
user642318 almost 4 years
I am looking for clean way to cast byte array to struct for client-server application. I know most ppl turn to gob package for this solution however I do not control the encoding for the application. that being said, I only programmed the server application not the client, there is a mutual contract for the protocol that is being exchanged.
The best I could come out is the following.
type T struct { A int16 B int8 C []byte } func main() { // Create a struct and write it. t := T{A: 99, B: 10} buf := &bytes.Buffer{} buf1 := []byte{5, 100, 100} fmt.Println(buf1) buf.Write(buf1) //err := binary.Write(buf, binary.BigEndian, t) //if err != nil { // panic(err) //} fmt.Println(buf) // Read into an empty struct. t = T{} err := binary.Read(buf, binary.BigEndian, &t) if err != nil { panic(err) } fmt.Printf("%d %d", t.A, t.B) }
However, as soon as number bytes does not coincide with the size of the struct, then go will send a panic. How can I modify this to work without the panic if undersize or oversize
-
user642318 almost 9 yearsAny idea how to cast to variable size
-
RoninDev almost 9 yearsDepends on your data structure. You can split your source array onto 2 parts. First part will contains only fixed-size data (A and B in your case 3 bytes). Second part will contains array data. In that way you need to create new structure, without array part, like
type T struct { A int16 B int8 }
. And decode both parts separately