前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >go中struct和[]byte互相转换

go中struct和[]byte互相转换

作者头像
solate
发布2019-07-22 16:26:51
18.3K0
发布2019-07-22 16:26:51
举报
文章被收录于专栏:solate 杂货铺solate 杂货铺

go中struct和[]byte互相转换

binary 包处理二进制

读取将r中的结构化二进制数据读入数据。 数据必须是指向固定大小值或固定大小值切片的指针。 从r读取的字节使用指定的字节顺序进行解码,并写入数据的连续字段。 当解码布尔值时,零字节被解码为假,并且任何其他非零字节被解码为真。 读入结构时,将跳过具有空白(_)字段名称的字段的字段数据; 即,空白字段名称可用于填充。 读入结构时,必须导出所有非空白字段,否则“读取”可能会出现混乱。

但是这种只能使用固定大小类型的数据,变长数据就会异常,例如string, slice 等

代码语言:javascript
复制
package main

import (
	"bytes"
	"encoding/binary"
	"fmt"
)

type T struct {
	A int64
	B float64
}

func main() {
	// Create a struct and write it.
	t := T{A: 0xEEFFEEFF, B: 3.14}
	buf := &bytes.Buffer{}
	err := binary.Write(buf, binary.BigEndian, t)
	if err != nil {
		panic(err)
	}
	fmt.Println(buf.Bytes())

	// Read into an empty struct.
	t = T{}
	err = binary.Read(buf, binary.BigEndian, &t)
	if err != nil {
		panic(err)
	}
	fmt.Printf("%x %f", t.A, t.B)
}

unsafe 包处理二进制

使用 unsafe 包

ByteToStruct

代码语言:javascript
复制
package main


import (
	"fmt"
	"unsafe"
)
type TestStructTobytes struct {
	data int64
}
type SliceMock struct {
	addr uintptr
	len  int
	cap  int
}

func main() {

	var testStruct = &TestStructTobytes{100}
	Len := unsafe.Sizeof(*testStruct)
	testBytes := &SliceMock{
		addr: uintptr(unsafe.Pointer(testStruct)),
		cap:  int(Len),
		len:  int(Len),
	}
	data := *(*[]byte)(unsafe.Pointer(testBytes))
	fmt.Println("[]byte is : ", data)
	var ptestStruct *TestStructTobytes = *(**TestStructTobytes)(unsafe.Pointer(&data))
	fmt.Println("ptestStruct.data is : ", ptestStruct.data)
}

StructToByte

代码语言:javascript
复制
package main

import (
	"fmt"
	"unsafe"
)

type TestStructTobytes struct {
	data int64
}
type SliceMock struct {
	addr uintptr
	len  int
	cap  int
}

func main() {

	var testStruct = &TestStructTobytes{100}
	Len := unsafe.Sizeof(*testStruct)
	testBytes := &SliceMock{
		addr: uintptr(unsafe.Pointer(testStruct)),
		cap:  int(Len),
		len:  int(Len),
	}
	data := *(*[]byte)(unsafe.Pointer(testBytes))
	fmt.Println("[]byte is : ", data)
}

gob 处理二进制

只使用于客户端服务端都使用gob包进行编码和解码的情况。也就是客户端服务端都是go写的,不试用于多种语言。

Gob流不支持函数和通道。试图在最顶层编码这些类型的值会导致失败。结构体中包含函数或者通道类型的字段的话,会视作非导出字段(忽略)处理。

Gob可以编码任意实现了GobEncoder接口或者encoding.BinaryMarshaler接口的类型的值(通过调用对应的方法),GobEncoder接口优先。

Gob可以解码任意实现了GobDecoder接口或者encoding.BinaryUnmarshaler接口的类型的值(通过调用对应的方法),同样GobDecoder接口优先。

代码语言:javascript
复制
package main

import (
	"bytes"
	"encoding/gob"
	"fmt"
)

// A struct with a mix of fields, used for the GOB example.
type complexData struct {
	N int
	S string
	M map[string]int
	P []byte
	C *complexData
	E Addr
}

type Addr struct {
	Comment string
}

func main() {

	testStruct := complexData{
		N: 23,
		S: "string data",
		M: map[string]int{"one": 1, "two": 2, "three": 3},
		P: []byte("abc"),
		C: &complexData{
			N: 256,
			S: "Recursive structs? Piece of cake!",
			M: map[string]int{"01": 1, "10": 2, "11": 3},
			E: Addr{
				Comment: "InnerTest123123123123",
			},
		},
		E: Addr{
			Comment: "Test123123123",
		},
	}

	fmt.Println("Outer complexData struct: ", testStruct)
	fmt.Println("Inner complexData struct: ", testStruct.C)
	fmt.Println("Inner complexData struct: ", testStruct.E)
	fmt.Println("===========================")

	var b bytes.Buffer
	enc := gob.NewEncoder(&b)
	err := enc.Encode(testStruct)
	if err != nil {
		fmt.Println(err)
	}

	dec := gob.NewDecoder(&b)
	var data complexData
	err = dec.Decode(&data)
	if err != nil {
		fmt.Println("Error decoding GOB data:", err)
		return
	}

	fmt.Println("Outer complexData struct: ", data)
	fmt.Println("Inner complexData struct: ", data.C)
	fmt.Println("Inner complexData struct: ", testStruct.E)

}

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • go中struct和[]byte互相转换
    • binary 包处理二进制
      • unsafe 包处理二进制
        • gob 处理二进制
        领券
        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档