2017-08-01 75 views
0

我是golang的新手,试图找出正确的方法来将一个字节块转换为正确的结构体。所有结构都以两个字节开头,这些字节决定了剩余字节的布局。在C中,我会指向内存块的开始,并将其转换为只包含这两个字节(下面的X)的简单结构,但在这里我得到一个无效的类型断言。我可能会在这里得到任何帮助,不胜感激。在golang中投射重叠结构

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

+0

的[进入结构和字节数组之间的转换(https://stackoverflow.com/questions/26372227/go-conversion-可能的复制结构体和字节数组之间) – captncraig

回答

0

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

  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

0

转到一般试图劝阻C-如内存摆弄它,除非非凡的谨慎和测试应用导致内存泄漏,不正确的行为,和安全漏洞。这并不意味着它是不可能的;实际上,正确名称为unsafe.Pointer就是为了这个目的而暴露的。谨慎使用它。

+0

'unsafe.Pointer'可能不需要这个。 '编码/二进制'可以做到这一点。 https://stackoverflow.com/questions/26372227/go-conversion-between-struct-and-byte-array。但我同意你的一般警告。 – captncraig