簡體   English   中英

在 Go 中,如何將結構轉換為字節數組?

[英]In Go, how can I convert a struct to a byte array?

我有一個我定義的結構實例,我想將它轉換為一個字節數組。 我試過 []byte(my_struct),但沒有用。 另外,我被指向了二進制文件 package ,但我不確定我應該使用哪個 function 以及我應該如何使用它。 一個例子將不勝感激。

一種可能的解決方案是"encoding/gob"標准包。 gob 包創建了一個編碼器/解碼器,可以將任何結構編碼為字節數組,然后將該數組解碼回結構。 有一個很棒的帖子,在這里

正如其他人指出的那樣,有必要使用這樣的包,因為結構本質上具有未知的大小並且無法轉換為字節數組。

我已經包含了一些代碼和play

package main

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

type P struct {
    X, Y, Z int
    Name    string
}

type Q struct {
    X, Y *int32
    Name string
}

func main() {
    // Initialize the encoder and decoder.  Normally enc and dec would be
    // bound to network connections and the encoder and decoder would
    // run in different processes.
    var network bytes.Buffer        // Stand-in for a network connection
    enc := gob.NewEncoder(&network) // Will write to network.
    dec := gob.NewDecoder(&network) // Will read from network.
    // Encode (send) the value.
    err := enc.Encode(P{3, 4, 5, "Pythagoras"})
    if err != nil {
        log.Fatal("encode error:", err)
    }

    // HERE ARE YOUR BYTES!!!!
    fmt.Println(network.Bytes())

    // Decode (receive) the value.
    var q Q
    err = dec.Decode(&q)
    if err != nil {
        log.Fatal("decode error:", err)
    }
    fmt.Printf("%q: {%d,%d}\n", q.Name, *q.X, *q.Y)
}

我假設你想要像 C 處理這個的方式。 沒有內置的方法可以做到這一點。 您必須為結構定義自己的字節序列化和反序列化。 二進制包將幫助您將結構中的字段編碼為可以添加到字節數組的字節,但您將負責指定字節數組中的長度和偏移量,以保存結構中的字段。

您的其他選擇是使用編碼包之一: http : //golang.org/pkg/encoding/,例如 gob 或 json。

編輯:

由於您希望按照您在評論中所說的那樣制作散列,因此最簡單的方法是使用[]byte(fmt.Sprintf("%v", struct))像這樣: http : []byte(fmt.Sprintf("%v", struct)) p/yY8mSdZ_kf

我知道這個線程很舊,但是沒有一個答案被接受,並且有一種非常簡單的方法可以做到這一點。

https://play.golang.org/p/TedsY455EBD

操場上的重要代碼

import (
  "bytes"
  "fmt"
  "encoding/json"
)

type MyStruct struct {
  Name string `json:"name"`
}

testStruct := MyStruct{"hello world"}
reqBodyBytes := new(bytes.Buffer)
json.NewEncoder(reqBodyBytes).Encode(testStruct)

reqBodyBytes.Bytes() // this is the []byte

使用json marshal,這是一個非常簡單的方法。

newFsConfig := dao.ConfigEntity{EnterpriseId:"testing"}
newFsConfigBytes, _ := json.Marshal(newFsConfig)

序列化可能是正確的答案。

但是,如果您同意不安全並且實際上需要將 struct 作為字節讀取,那么依賴字節數組內存表示可能比依賴字節切片內部結構要好一些。

type Struct struct {
    Src int32
    Dst int32
    SrcPort uint16
    DstPort uint16
}

const sz = int(unsafe.SizeOf(Struct{}))
var asByteSlice []byte = (*(*[sz]byte)(unsafe.Pointer(&struct_value)))[:]

工作並提供對結構的讀寫視圖,零拷貝。 兩個“不安全”應該足以暗示它可能會嚴重損壞。

您應該使用字節緩沖區而不是字符串,其他建議的方法創建可變長度的 SHA1,SHA1 標准長度必須為 20 字節(160 位)

package main

import (
    "crypto/sha1"
    "fmt"
    "encoding/binary"
    "bytes"
)

type myStruct struct {
    ID   string
    Data string
}

func main() {
    var bin_buf bytes.Buffer
    x := myStruct{"1", "Hello"}
    binary.Write(&bin_buf, binary.BigEndian, x)
    fmt.Printf("% x", sha1.Sum(bin_buf.Bytes()))
}

自己試試: http : //play.golang.org/p/8YuM6VIlLV

這是一個非常簡單的方法,而且效果很好。

package main

import (
    "crypto/sha1"
    "fmt"
    "encoding/binary"
    "bytes"
)

type myStruct struct {
    ID   [10]byte
    Data [10]byte
}

func main() {
    var bin_buf bytes.Buffer
    x := myStruct{"1", "Hello"}
    binary.Write(&bin_buf, binary.BigEndian, x)
    fmt.Printf("% x", sha1.Sum(bin_buf.Bytes()))
}

binary.Write 采用具有固定長度內存分配數據類型的結構。

json.Marshal 是將結構體轉換為 []byte 的最佳選擇,請參見下面的示例:

package main

import (
    "encoding/json"
    "fmt"
)

type ExampleConvertToByteArray struct {
    Name    string
    SurName string
}

func main() {

    example := ExampleConvertToByteArray{
        Name:    "James",
        SurName: "Camara",
    }
    
    var exampleBytes []byte
    var err error

    exampleBytes, err = json.Marshal(example)
    if err != nil {
        print(err)
        return
    }

    fmt.Println(string(exampleBytes))
}

去游樂場 -> https://play.golang.org/p/mnB9Cxy-2H3

看看https://blog.golang.org/go-slices-usage-and-internals具體切片內部。 這個想法是模仿切片的內部結構並指向我們的結構而不是字節序列:

package main

import (
    "fmt"
    "unsafe"
)

// our structure
type A struct {
    Src int32
    Dst int32
    SrcPort uint16
    DstPort uint16
}

// that is how we mimic a slice
type ByteSliceA struct {
    Addr *A
    Len int
    Cap int
}

func main() {
    // structure with some data
    a := A{0x04030201,0x08070605,0x0A09, 0x0C0B}

    // create a slice structure
    sb := &ByteSliceA{&a, 12, 12} // struct is 12 bytes long, e.g. unsafe.Sizeof(a) is 12

    // take a pointer of our slice mimicking struct and cast *[]byte on it:     
    var byteSlice []byte = *(*[]byte)(unsafe.Pointer(sb))

    fmt.Printf("%v\n", byteSlice)
}

輸出:

[1 2 3 4 5 6 7 8 9 10 11 12]

https://play.golang.org/p/Rh_yrscRDV6

你有沒有考慮將它序列化到bson? http://labix.org/gobson

var v any
b := (*[unsafe.Sizeof(v)]byte)(unsafe.Pointer(&v))
c := b[:]

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM