Introduction of binary protocol gob and msgpack

Time:2021-6-5

This paper mainly introduces the basic use of binary protocol gob and msgpack.

Recently, when writing a session service of gin framework, we encountered a problem. The number types (integer, floating point, etc.) stored in the JSON package of go language in the serialized empty interface are serialized into float64 type.

We construct a structure as follows:

type s struct {
	data map[string]interface{}
}

Problems of JSON serialization

func jsonDemo() {
	var s1 = s{
		data: make(map[string]interface{}, 8),
	}
	s1.data["count"] = 1
	ret, err := json.Marshal(s1.data)
	if err != nil {
		fmt.Println("marshal failed", err)
	}
	fmt.Printf("%#v\n", string(ret))
	var s2 = s{
		data: make(map[string]interface{}, 8),
	}
	err = json.Unmarshal(ret, &s2.data)
	if err != nil {
		fmt.Println("unmarshal failed", err)
	}
	fmt.Println(s2)
	for _, v := range s2.data {
		fmt.Printf("value:%v, type:%T\n", v, v)
	}
}

Output results:

"{\"count\":1}"
{map[count:1]}
value:1, type:float64

Gob serialization example

The standard library gob is a “private” encoding and decoding method provided by golang. Its efficiency is higher than that of JSON, XML and so on. It is especially suitable for data transfer between go language programs.

func gobDemo() {
	var s1 = s{
		data: make(map[string]interface{}, 8),
	}
	s1.data["count"] = 1
	// encode
	buf := new(bytes.Buffer)
	enc := gob.NewEncoder(buf)
	err := enc.Encode(s1.data)
	if err != nil {
		fmt.Println("gob encode failed, err:", err)
		return
	}
	b := buf.Bytes()
	fmt.Println(b)
	var s2 = s{
		data: make(map[string]interface{}, 8),
	}
	// decode
	dec := gob.NewDecoder(bytes.NewBuffer(b))
	err = dec.Decode(&s2.data)
	if err != nil {
		fmt.Println("gob decode failed, err", err)
		return
	}
	fmt.Println(s2.data)
	for _, v := range s2.data {
		fmt.Printf("value:%v, type:%T\n", v, v)
	}
}

msgpack

Message pack is an efficient binary serialization format. It allows you to exchange data between multiple languages, such as JSON. But it’s faster and smaller.

install

go get -u github.com/vmihailenco/msgpack

Examples

package main

import (
	"fmt"

	"github.com/vmihailenco/msgpack"
)

// msgpack demo

type Person struct {
	Name   string
	Age    int
	Gender string
}

func main() {
	p1 := Person{
		Name: "Shahe Naza",
		Age:    18,
		Gender: "male",
	}
	// marshal
	b, err := msgpack.Marshal(p1)
	if err != nil {
		fmt.Printf("msgpack marshal failed,err:%v", err)
		return
	}

	// unmarshal
	var p2 Person
	err = msgpack.Unmarshal(b, &p2)
	if err != nil {
		fmt.Printf("msgpack unmarshal failed,err:%v", err)
		return
	}
	FMT. Printf ("P2:% ####, P2) // P2: main. Person {Name:" shahenaza ", age: 18, gender:" male "}
}