2017-08-01 73 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