【问题标题】:casting overlapping structs in golang在golang中铸造重叠结构
【发布时间】:2017-08-01 13:55:28
【问题描述】:

我是 golang 新手,并试图找出将字节块转换为正确结构的正确方法。所有结构都以两个字节开始,这些字节指示剩余字节的布局。在 C 语言中,我将指向内存块的开头并将其转换为仅包含这两个字节(下面的 X)的简单结构,但在这里我得到一个无效的类型断言。我可能会在这里为您提供任何帮助。

package main

import (
    "fmt"
)

type A struct {
    tag   byte
    ver   byte
    data1 int
    data2 int
    data3 int
}

type B struct {
    tag   byte
    ver   byte
    data1 float32
}

type X struct {
    tag byte
    ver byte
}

func main() {
    var a A
    a.tag = 1
    a.ver = 1
    x := a.(X)

    fmt.Printf("%d,%d", x.tag, x.ver)
}

playground link

【问题讨论】:

标签: go


【解决方案1】:

这是我的解决方案。它涉及一些不同的技巧:

  1. 在各个结构中嵌入共享结构。
  2. 使用encoding/binary 包将字节加载到结构中。
  3. 用前两个字节填充标头结构,然后决定制作和填充哪个子类型。
  4. 对这类事情总是使用固定长度的 int 类型。
  5. 您的字段名称必须是 UpperCase 才能从 encoding/binary 填写
  6. 这是一种管理 marshalling.unmarshalling 数据的非常脆弱的方法,但我相信您知道这一点。

这是我的解决方案:

package main

import (
    "bytes"
    "encoding/binary"
    "fmt"
    "log"
)

type A struct {
    X
    Data1 int32
    Data2 int32
    Data3 int32
}

type B struct {
    X
    Data1 int32
}

type X struct {
    Tag byte
    Ver byte
}

func main() {
    var err error
    data := []byte{1, 1, 0, 0, 0, 42}
    hdr := X{}

    err = binary.Read(bytes.NewReader(data[:2]), binary.BigEndian, &hdr)
    if err != nil {
        log.Fatal(err)
    }
    fmt.Println(hdr.Tag, hdr.Ver)

    if hdr.Tag == 1 {
        b := B{}
        err = binary.Read(bytes.NewReader(data), binary.BigEndian, &b)
        if err != nil {
            log.Fatal(err)
        }
        fmt.Println(b.Data1)
    }

}

playground link

【讨论】:

    【解决方案2】:

    Go 通常会尝试阻止类似 C 的内存摆弄,因为它会导致内存泄漏、不正确的行为和安全漏洞,除非特别小心和测试。但这并不意味着这是不可能的;事实上,恰如其分地命名unsafe.Pointer 就是为了这个目的而公开的。谨慎使用。

    【讨论】:

    猜你喜欢
    • 2015-10-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多