У меня есть экземпляр структуры, которую я определил, и я хотел бы преобразовать ее в массив байтов. Я попробовал [] byte (my_struct), но это не сработало. Кроме того, я указал на двоичный пакет , но я не уверен, какую функцию я должен использовать и как я должен его использовать. В качестве примера мы будем благодарны.
В Go, как я могу преобразовать структуру в массив байтов?
Ответ 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]
Ответ 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)