65

我有一个我定义的结构实例,我想将它转换为一个字节数组。我尝试了 []byte(my_struct),但没有奏效。另外,我被指向二进制包,但我不确定应该使用哪个函数以及应该如何使用它。一个例子将不胜感激。

4

10 回答 10

40

一种可能的解决方案是"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)
}
于 2018-01-07T04:33:23.720 回答
34

我假设您想要类似 C 处理此问题的方式。没有内置的方法可以做到这一点。您将必须为您的结构定义自己的序列化和反序列化字节。二进制包将帮助您将结构中的字段编码为可以添加到字节数组的字节,但您将负责指定字节数组中将保存结构中的字段的长度和偏移量。

您的其他选择是使用以下编码包之一:http ://golang.org/pkg/encoding/ ,例如 gob 或 json。

编辑:

既然你想要这个来制作你在评论中所说的哈希,最容易做的事情就是这样使用[]byte(fmt.Sprintf("%v", struct))http ://play.golang.org/p/yY8mSdZ_kf

于 2013-05-02T04:52:50.557 回答
25

我知道这个线程很旧,但没有一个答案被接受,并且有一个非常简单的方法可以做到这一点。

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
于 2018-04-20T16:44:59.363 回答
19

只需使用 json marshal,这是一种非常简单的方法。

newFsConfig := dao.ConfigEntity{EnterpriseId:"testing"}
newFsConfigBytes, _ := json.Marshal(newFsConfig)
于 2019-07-16T07:55:31.057 回答
14

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

但是如果你同意不安全并且实际上需要将结构读取为字节,那么依赖字节数组内存表示可能比依赖字节内部结构要好一些。

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

工作并提供结构零拷贝的读写视图。两个“不安全”应该足以暗示它可能会严重损坏。

于 2019-05-23T10:13:13.540 回答
11

您应该使用字节缓冲区而不是字符串,其他建议的方法创建可变长度的 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

这是一个非常简单的方法,而且效果很好。

于 2015-01-21T17:16:50.083 回答
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()))
}

binary.Write 采用具有固定长度内存分配数据类型的结构。

于 2019-05-09T16:25:20.043 回答
7

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

于 2020-12-18T14:11:24.707 回答
3

看看https://blog.golang.org/go-slices-usage-and-internals 具体切片内部。这个想法是模仿 slice 的内部结构并指向我们的结构而不是字节序列:

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

于 2018-08-21T16:37:21.617 回答
2

Have you considered serializing it to bson? http://labix.org/gobson

于 2013-05-02T13:50:24.903 回答