В Go, как я могу преобразовать структуру в массив байтов? - программирование
Подтвердить что ты не робот

В Go, как я могу преобразовать структуру в массив байтов?

У меня есть экземпляр структуры, которую я определил, и я хотел бы преобразовать ее в массив байтов. Я попробовал [] byte (my_struct), но это не сработало. Кроме того, я указал на двоичный пакет , но я не уверен, какую функцию я должен использовать и как я должен его использовать. В качестве примера мы будем благодарны.

4b9b3361

Ответ 1

Я предполагаю, что вы хотите что-то вроде того, как C справляется с этим. Для этого нет встроенного способа. Вам нужно будет определить свою сериализацию и десериализацию в и из байтов для вашей структуры. Бинарный пакет поможет вам кодировать поля в вашей структуре в байты, которые вы можете добавить в массив байтов, но вы будете нести ответственность за указание длин и смещений в массиве байтов, которые будут содержать поля из вашей структуры.

Ваши другие варианты - использовать один из пакетов кодирования: http://golang.org/pkg/encoding/, например gob или json.

EDIT:

Поскольку вы хотите, чтобы это создавало хэш, как вы говорите в своем комментарии, проще всего использовать []byte(fmt.Sprintf("%v", struct)): http://play.golang.org/p/yY8mSdZ_kf

Ответ 2

Одним из возможных решений является стандартный пакет "encoding/gob". Пакет gob создает кодер/декодер, который может кодировать любую структуру в массив байтов, а затем декодировать этот массив обратно в структуру. Там отличный пост, здесь.

Как указывали другие, необходимо использовать такой пакет, потому что структуры по своей природе имеют неизвестные размеры и не могут быть преобразованы в массивы байтов.

Я включил некоторый код и игру.

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

Ответ 3

Вы должны использовать буфер байтов вместо строки, другие предлагаемые методы создают 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

Это очень простой способ, и он отлично работает.

Ответ 4

Я знаю, что эта ветка старая, но ни один из ответов не был принят, и есть довольно простой способ сделать это.

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

Ответ 5

Рассматривали ли вы его сериализацию в bson? http://labix.org/gobson

Ответ 6

Посмотрите на 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

Ответ 7

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

Двоичный файл .Write принимает структуру, которая имеет фиксированный размер памяти, выделенный тип данных.

Ответ 8

Сериализация, скорее всего, правильный ответ.

Но если вы даете согласие на небезопасность и действительно хотите читать 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)))[:]

Работает и обеспечивает чтение и запись в структуру, нулевое копирование. Два "небезопасных" должны намекнуть достаточно, чтобы он мог плохо сломаться.

Ответ 9

Просто используйте json marshal, это очень простой способ.

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