Go 序列化
应用程序的交互,即数据的交互,永远离不开序列化,常见的数据交互格式是 json。
一、Go 语言中的序列化和反序列化
go 语言中序列化对比:
方式 | 优点 | 缺点 |
---|---|---|
binary | 性能高 | 不支持不确定大小类型 int、slice、string |
protobuf | 支持多种类型,性能高 | 需要单独存放结构,如果结构变动需要重新生成 .pb.go 文件 |
gob | 支持多种类型 | 性能低 |
json | 支持多种类型 | 性能低于 binary 和 protobuf |
xml | 支持多种类型 | 性能低于 json |
二、json
json 格式数据是现在数据交互用的最多的数据格式,go 一般通过 json.Marshal()进行序列化,通过 json.Unmarshal()反序列化。
type Message struct {
Id uint64 `json:"id"`
Size uint64 `json:"size"`
Data string `json:"data"`
}
func JsonEncodeDecode() {
m1 := Message{3, 1024, "json"}
var buf []byte
var err error
if buf, err = json.Marshal(m1); err != nil {
log.Fatal("json marshal error:", err)
}
var m2 Message
if err = json.Unmarshal(buf, &m2); err != nil {
log.Fatal("json unmarshal error:", err)
}
}
三、Gob
Gob(Go binary 的缩写)是 Go 语言自己以二进制形式序列化和反序列化程序数据的格式,其方法在 encoding 中,只能在 go 程序之间进行数据交互。
type Message struct {
Id uint64
Size uint64
Data string
}
func GobEncodeDecode() {
m1 := Message{2, 1024, "gob"}
var buf bytes.Buffer
enc := gob.NewEncoder(&buf)
dec := gob.NewDecoder(&buf)
if err := enc.Encode(m1); err != nil {
log.Fatal("encode error:", err)
}
var m2 Message
if err := dec.Decode(&m2); err != nil {
log.Fatal("decode error:", err)
}
}
四、Binary
endoding 包中的 binnary 主要用于二进制数据序列化,但是局限性较高。
注意:数据类型必须是固定大小,如果字段中有不确定大小的类型,如 int,slice,string 等,则会报错。
字节序列方式(order):
binary.BigEndian(大端模式):内存的低地址存放着数据高位
binary.LittleEndian(小端模式):内存的低地址存放着数据地位
type Message struct {
Id uint64
Size uint64
}
func BinaryRW() {
m1 := Message{1, 1024}
buf := new(bytes.Buffer)
if err := binary.Write(buf, binary.LittleEndian, m1); err != nil {
log.Fatal("binary write error:", err)
}
var m2 Message
if err := binary.Read(buf, binary.LittleEndian, &m2); err != nil {
log.Fatal("binary read error:", err)
}
}
五、Protobuf
ProtoBuf 并不是 go 语言中包自带的,需要自行安装 protoc 编译器,以及 protoc 库以及生成相关的类
syntax = "proto2";
package example;
message Message {
required uint64 id = 1;
required uint64 size = 2;
required string data = 3;
}
func ProtoEncodeDecode() {
m1 := &example.Message{
Id: proto.Uint64(4),
Size: proto.Uint64(1024),
Data: proto.String("proto"),
}
buf, err := proto.Marshal(m1)
if err != nil {
log.Fatal("proto marshal error:", err)
}
var m2 example.Message
if err = proto.Unmarshal(buf, &m2); err != nil {
log.Fatal("proto unmarshal error:", err)
}
fmt.Println(m2.GetId(), m2.GetSize(), m2.GetData())
}
六、XML
Go 语言内置的 encoding/xml 包可以用在结构体和 XML 格式之间进行编解码,其方式跟 encoding/json 包类似
type Message struct {
Id uint64
Size uint64
Data string
}
func XmlEncodeDecode() {
m1 := Message{2, 1024, "gob"}
var buf bytes.Buffer
enc := xml.NewEncoder(&buf)
dec := xml.NewDecoder(&buf)
if err := enc.Encode(m1); err != nil {
log.Fatal("encode error:", err)
}
var m2 Message
if err := dec.Decode(&m2); err != nil {
log.Fatal("decode error:", err)
}
}