wake-up-neo.com

Wie kann ich in Go eine Struktur in ein Byte-Array konvertieren?

Ich habe eine Instanz einer von mir definierten Struktur und möchte diese in ein Byte-Array konvertieren. Ich habe [] Byte (my_struct) ausprobiert, aber das hat nicht funktioniert. Ich wurde auch auf das binary package hingewiesen, bin mir aber nicht sicher, welche Funktion ich verwenden soll und wie ich es verwenden soll. Ein Beispiel wäre sehr dankbar.

23
abw333

Ich nehme an, Sie wollen so etwas wie C damit umgehen. Dafür gibt es keine eingebaute Möglichkeit. Sie müssen Ihre eigene Serialisierung und Deserialisierung für und von Bytes für Ihre Struktur definieren. Das Binärpaket hilft Ihnen beim Kodieren der Felder in Ihrer Struktur in Bytes, die Sie dem Bytearray hinzufügen können. Sie müssen jedoch die Längen und Offsets im Bytearray angeben, die die Felder Ihrer Struktur enthalten sollen.

Ihre anderen Optionen sind, eines der Kodierungspakete zu verwenden: http://golang.org/pkg/encoding/ wie gob oder json.

EDIT:

Da Sie dies für die Erstellung eines Hashs wünschen, wie Sie in Ihrem Kommentar sagen, ist es am einfachsten, []byte(fmt.Sprintf("%v", struct)) zu verwenden: http://play.golang.org/p/yY8mSdZ_kf

20
Jeremy Wall

Eine mögliche Lösung ist das Standardpaket "encoding/gob". Das gob-Paket erstellt einen Encoder/Decoder, der jede Struktur in ein Byte-Array codieren und dieses Array dann wieder in eine Struktur decodieren kann. Es gibt einen großartigen Beitrag, hier .

Wie andere darauf hingewiesen haben, ist es notwendig, ein solches Paket zu verwenden, da die Struktur von Natur aus unbekannte Größen aufweist und nicht in Byte-Arrays umgewandelt werden kann.

Ich habe etwas Code und ein play eingefügt.

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)
}
11
Adam

Sie sollten anstelle eines Strings einen Byte-Puffer verwenden. Die anderen vorgeschlagenen Methoden erstellen einen SHA1 mit variabler Länge. Die Standardlänge des SHA1 muss 20 Byte (160 Bit) betragen.

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()))
}

Probieren Sie es selbst aus: http://play.golang.org/p/8YuM6VIlLV

Es ist eine wirklich einfache Methode und funktioniert prima.

Ich weiß, dass dieser Thread alt ist, aber keine der Antworten wurde akzeptiert und es gibt einen ziemlich einfachen Weg, dies zu tun.

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

wichtiger Code vom Spielplatz

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
6
Cody Jacques

Haben Sie darüber nachgedacht, es zu bson zu serialisieren? http://labix.org/gobson

2
Erik St. Martin

Werfen Sie einen Blick auf https://blog.golang.org/go-slices-usage-and-internals Schneiden Sie speziell die internen Elemente. Die Idee ist, die interne Struktur von Slice zu imitieren und auf unsere Struktur statt auf eine Bytefolge zu verweisen:

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)
}

Ausgabe:

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

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

0
Kax
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 verwendet eine Struktur, deren Datentyp einem Speicher mit fester Länge zugewiesen ist.

0
Asnim P Ansari

Serialisierung ist wahrscheinlich die richtige Antwort.

Aber wenn Sie der Unsicherheit zustimmen und die Struktur tatsächlich als Byte lesen müssen, ist die Verwendung von Byte Array Speicherdarstellung möglicherweise etwas besser als die Verwendung von Byte Slice interne Struktur.

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)))[:]

Funktioniert und bietet Schreib-/Leseansicht in struct, zero-copy. Zwei "unsichere" sollten genug andeuten, dass es schlecht brechen kann.

0
temoto

Benutze einfach json marshal - das ist ein sehr einfacher Weg.

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