arrays - iterating - in array golang
En Go, ¿cómo puedo convertir una estructura a una matriz de bytes? (6)
¿Has considerado serializarlo a bson? http://labix.org/gobson
Tengo una instancia de una estructura que definí y me gustaría convertirla en una matriz de bytes. Intenté [] byte (my_struct), pero eso no funcionó. Además, me indicaron el paquete binario , pero no estoy seguro de qué función debo usar y cómo debo usarla. Un ejemplo sería muy apreciado.
Debe usar un búfer de bytes en lugar de una cadena, los otros métodos sugeridos crean un SHA1 de longitud variable, la longitud estándar de SHA1 debe ser de 20 bytes (160 bits)
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()))
}
Pruébelo usted mismo: http://play.golang.org/p/8YuM6VIlLV
Es un método muy fácil y funciona muy bien.
Eche un vistazo a https://blog.golang.org/go-slices-usage-and-internals Específicamente partes internas. La idea es imitar la estructura interna del segmento y apuntar a nuestra estructura en lugar de a una secuencia de bytes:
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)
}
Salida:
[1 2 3 4 5 6 7 8 9 10 11 12]
Sé que este hilo es antiguo, pero ninguna de las respuestas fue aceptada, y hay una manera bastante simple de hacerlo.
https://play.golang.org/p/TedsY455EBD
código importante del patio
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
Supongo que quieres algo como la forma en que C maneja esto. No hay una forma integrada de hacer eso. Deberá definir su propia serialización y deserialización desde y hacia bytes para su estructura. El paquete binario le ayudará a codificar los campos en su estructura a bytes que puede agregar a la matriz de bytes, pero será responsable de especificar las longitudes y las compensaciones en la matriz de bytes que contendrán los campos de su estructura.
Sus otras opciones son usar uno de los paquetes de codificación: http://golang.org/pkg/encoding/ como gob o json.
EDITAR:
Como quiere hacer un hash como dice en su comentario, lo más fácil es usar []byte(fmt.Sprintf("%v", struct))
así: http://play.golang.org/p/yY8mSdZ_kf
Una posible solución es el paquete estándar "encoding/gob"
. El paquete gob crea un codificador / decodificador que puede codificar cualquier estructura en una matriz de bytes y luego decodificar esa matriz nuevamente en una estructura. Hay un gran post, here .
Como han señalado otros, es necesario usar un paquete como este porque las estructuras, por su naturaleza, tienen tamaños desconocidos y no se pueden convertir en matrices de bytes.
He incluido un código y una 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)
}