在Go中,如何将结构转换为字节数组?

abw*_*333 29 arrays byte struct go

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

Jer*_*all 22

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

您的其他选择是使用其中一个编码包:http://golang.org/pkg/encoding/,如gob或json.

编辑:

因为你想要在你的评论中想要制作哈希,[]byte(fmt.Sprintf("%v", struct))所以最简单的方法就是这样使用:http://play.golang.org/p/yY8mSdZ_kf


小智 14

只使用 json 元帅?这是一个非常简单的方法。

newFsConfig := dao.ConfigEntity{EnterpriseId:"testing"}
newFsConfigBytes, _ := json.Marshal(newFsConfig)
Run Code Online (Sandbox Code Playgroud)

  • 确切地说,我只是向下滚动查看是否有人给出了这个答案。对于这样一个简单的问题,其余的答案都过于复杂。好工作! (2认同)

Ada*_*dam 13

一种可能的解决方案是"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)
}
Run Code Online (Sandbox Code Playgroud)

  • 这可能是一个愚蠢的问题,但 gob 是否也序列化未导出的字段? (2认同)
  • @苗条 一点也不!实际上我不是 100% 确定,但我希望不会。与encoding/json 相同,不序列化未导出的字段。 (2认同)

tem*_*oto 12

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

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

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)))[:]
Run Code Online (Sandbox Code Playgroud)

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


小智 11

我知道这个帖子已经过时了,但没有一个答案被接受,并且有一个非常简单的方法可以做到这一点.

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
Run Code Online (Sandbox Code Playgroud)

  • 这会将结构转换为"JSON"格式的字节数组.我假设问题是关于将结构转换为"二进制"格式的字节数组(用于较低的内存/磁盘消耗). (4认同)

小智 9

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))
}
Run Code Online (Sandbox Code Playgroud)

去游乐场 -> https://play.golang.org/p/mnB9Cxy-2H3


Hug*_*zar 8

您应该使用,而不是一个串的字节缓冲器时,其他建议的方法创建可变长度的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()))
}
Run Code Online (Sandbox Code Playgroud)

亲自尝试:http://play.golang.org/p/8YuM6VIlLV

这是一种非常简单的方法,效果很好.

  • 看起来不像这样,因为`myStruct`不是固定大小.https://play.golang.org/p/IGA_lgRVNX (8认同)
  • 它有用吗?检查从binary.Write返回的错误显示"binary.Write:invalid type main.myStruct".... (3认同)
  • 仅限链接答案已弃用. (2认同)
  • 证明这行不通。不过会是一件很棒的事情.. https://play.golang.org/p/gpBUXMnaOUJ (2认同)

Asn*_*ari 5

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()))
}
Run Code Online (Sandbox Code Playgroud)

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