在golang

时间:2017-08-01 13:55:29

标签: go

我是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

2 个答案:

答案 0 :(得分:0)

Go通常会试图阻止类似C的内存摆弄,因为它会导致内存泄漏,不正确的行为和安全漏洞,除非应用非常谨慎和测试。但这并不意味着它是不可能的;实际上,恰当地命名的unsafe.Pointer正是为了这个目的。请谨慎使用。

答案 1 :(得分:0)

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

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

    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