dpzo13732 2018-12-13 20:49
浏览 85
已采纳

Golang中的对齐

I am implementing a network packet in golang. It was already implemented in C++. The purpose is to make the golang implemented client communicate with C++ implemented server.

They will communicate by packet. The packet struct is:

type Packet struct {
    length   uint32
    nameLen  uint8
    data     []byte
} // in golang

struct Packet {
    uint32_t length;
    uint8_t  nameLen;
    byte     data[];
} // in C++

Their underlined structure is byte array. When receiving a message in byte array format. We need to translate it into Packet.

auto p = reinterpret_cast<Packet*>(buffer); // in c++
(buffer's alignment is manually set as 64)

p := (Packet)(unsafe.Pointer(&buffer)) // in golang

To make them communicate, their struct alignment should keep the same.

Here comes the question: After printing out their alignment, I get this:

type Packet struct {
    length  uint32 // alignment 8
    nameLen uint8  // alignment 8
    data    []byte // alignment 8
}
struct Packet {
    uint32_t length;  // alignment 4
    uint8    nameLen; // alignment 4
    data     []byte;  // alignment 1
}

They will decode the message differently due to the alignment is different.

I can not change the C++ code.

Q1: Is there any way to set struct fields alignment in golang?

Q2: Is there a better way to implement golang Packet to avoid alignment mismatch when casting buffer into packet?

  • 写回答

2条回答 默认 最新

  • doufei1988 2018-12-24 20:33
    关注

    According to Adrian and Volker's comment,

    Q1: No

    Q2: Do some programming to unpack fields individually.

    In encoding/binary package, we have

    func PutUVarint
    

    It encodes a uint64 into buf and returns the number of bytes written. Somehow this package dont have public function to encode uint32. So I did something similar:

    func PutUint32(b []byte, v uint32) {
        _ = b[3] // early check
        b[0] = byte(v)
        b[1] = byte(v >> 8)
        b[2] = byte(v >> 16)
        b[3] = byte(v >> 24)
    } // assume it's littleEndian
    
    // to store packet length into buffer.
    PutUint32(buffer, pkt.length)
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(1条)

报告相同问题?

悬赏问题

  • ¥20 机器学习能否像多层线性模型一样处理嵌套数据
  • ¥20 西门子S7-Graph,S7-300,梯形图
  • ¥50 用易语言http 访问不了网页
  • ¥50 safari浏览器fetch提交数据后数据丢失问题
  • ¥15 matlab不知道怎么改,求解答!!
  • ¥15 永磁直线电机的电流环pi调不出来
  • ¥15 用stata实现聚类的代码
  • ¥15 请问paddlehub能支持移动端开发吗?在Android studio上该如何部署?
  • ¥20 docker里部署springboot项目,访问不到扬声器
  • ¥15 netty整合springboot之后自动重连失效