我正在Go中编写客户端 - 服务器应用程序。我想在Go中执行类似C的类型转换。
E.g。在Go
type packet struct {
opcode uint16
data [1024]byte
}
var pkt1 packet
...
n, raddr, err := conn.ReadFromUDP(pkt1) // error here
此外,我想执行类似C的memcpy(),这将允许我直接将接收到的网络字节流映射到结构。
e.g。以上收到的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)
}
答案 0 :(得分:16)
unsafe.Pointer
是不安全的,你实际上并不需要它。请改用encoding/binary
包:
// 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", t.A, t.B)
正如您所看到的,它非常巧妙地处理大小和字节序。
答案 1 :(得分:2)
你必须使用不安全的,在64位系统上uint
也是8个字节,如果你想要4个字节,你必须使用uint32。
它丑陋,不安全,你必须自己处理结束。
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]))
}
}
答案 2 :(得分:2)
感谢您的回答,我相信它们完美无缺。但在我的情况下,我更感兴趣的是解析作为网络数据包接收的[]字节缓冲区。我使用以下方法来解析缓冲区。
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
从结构体构造[]字节流时,可以使用以下方法
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)
我希望这能提供关于如何将[]字节流转换为struct并将struct转换回[]字节流的一般概念。
答案 3 :(得分:1)
我遇到了同样的问题,我使用“encoding / binary”包解决了这个问题。这是一个例子:
IllegalStateException
以下是正在运行的示例:https://play.golang.org/p/Q3LjaAWDMh