Convert go between array struct and byte

I am writing a client-server application in Go. I want to cast type C in Go.

eg. in go

type packet struct { opcode uint16 data [1024]byte } var pkt1 packet ... n, raddr, err := conn.ReadFromUDP(pkt1) // error here 

I also want to execute C-like memcpy (), which will allow me to directly display the network byte stream received in the struct.

eg. with the above pkt1

 type file_info struct { file_size uint32 // 4 bytes file_name [1020]byte } var file file_info if (pkt1.opcode == WRITE) { memcpy(&file, pkt1.data, 1024) } 
+6
source share
4 answers

unsafe.Pointer is, well, unsafe, and you really don't need it. Use encoding/binary instead:

 // Create a struct and write it. t := T{A: 0xEEFFEEFF, B: 3.14} buf := &bytes.Buffer{} err := binary.Write(buf, binary.BigEndian, t) if err != nil { panic(err) } fmt.Println(buf.Bytes()) // Read into an empty struct. t = T{} err = binary.Read(buf, binary.BigEndian, &t) if err != nil { panic(err) } fmt.Printf("%x %f", tA, tB) 

Playground

As you can see, it handles dimensions and approval fairly neatly.

+13
source

You will need to use insecure, and uint - 8 bytes on 64-bit systems, you need to use uint32 if you want 4 bytes.

This is ugly, unsafe, and you need to deal with enthusiasm yourself.

 type packet struct { opcode uint16 data [1022]byte } type file_info struct { file_size uint32 // 4 bytes file_name [1018]byte //this struct has to fit in packet.data } func makeData() []byte { fi := file_info{file_size: 1 << 20} copy(fi.file_name[:], []byte("test.x64")) p := packet{ opcode: 1, data: *(*[1022]byte)(unsafe.Pointer(&fi)), } mem := *(*[1022]byte)(unsafe.Pointer(&p)) return mem[:] } func main() { data := makeData() fmt.Println(data) p := (*packet)(unsafe.Pointer(&data[0])) if p.opcode == 1 { fi := (*file_info)(unsafe.Pointer(&p.data[0])) fmt.Println(fi.file_size, string(fi.file_name[:8])) } } 

play

+2
source

Thanks for the answers, and I'm sure they work great. But in my case, I was more interested in parsing [] the byte buffer received as a network packet. I used the following method to parse the buffer.

 var data []byte // holds the network packet received opcode := binary.BigEndian.Uint16(data) // this will get first 2 bytes to be interpreted as uint16 number raw_data := data[2:len(data)] // this will copy rest of the raw data in to raw_data byte stream 

When building a [] byte stream from a structure, you can use the following method

 type packet struct { opcode uint16 blk_no uint16 data string } pkt := packet{opcode: 2, blk_no: 1, data: "testing"} var buf []byte = make([]byte, 50) // make sure the data string is less than 46 bytes offset := 0 binary.BigEndian.PutUint16(buf[offset:], pkt.opcode) offset = offset + 2 binary.BigEndian.PutUint16(buf[offset:], pkt.blk_no) offset = offset + 2 bytes_copied := copy(buf[offset:], pkt.data) 

Hopefully this gives a general idea of ​​how to convert a byte stream [] into a structure and a structure back into a [] byte stream.

+2
source

I had the same problem and solved it with the "encoding / binary" package. Here is an example:

 package main import ( "bytes" "fmt" "encoding/binary" ) func main() { p := fmt.Println b := []byte{43, 1, 0} myStruct := MyStruct{} err := binary.Read(bytes.NewBuffer(b[:]), binary.BigEndian, &myStruct) if err != nil { panic(err) } p(myStruct) } type MyStruct struct { Num uint8 Num2 uint16 } 

Here is an example of work: https://play.golang.org/p/Q3LjaAWDMh

+1
source

Source: https://habr.com/ru/post/976751/


All Articles