Skip to content

Latest commit

 

History

History
202 lines (148 loc) · 4.81 KB

6.3-通信数据格式(json|xml|gob|msgpack|protobuf).md

File metadata and controls

202 lines (148 loc) · 4.81 KB

6.3 通信数据格式

1、JSON

go一般是使用encoding/json包实现JSON的编码和解码.可以将json字符串解码为struct结构体map字典等等

         json.Marshal(v interface{}) ([]byte, error) //json编码
         json.Unmarshal(data []byte, v interface{}) error //json解码  v需要传入一个指针      
package main

import (
	"encoding/json"
	"fmt"
)

type Msg struct {
	Code    int         `json:"code"`
	Message string      `json:"msg"`
	Data    interface{} `json:"data"`
}

func main() {
	msg := Msg{Code: 0, Message: "Hello", Data: 1}
	m, err := json.Marshal(msg)
	if err != nil {
		fmt.Println(err)
		return
	}
	fmt.Println(m, string(m))

	var map1 map[string]interface{}
	err = json.Unmarshal(m, &map1)
	fmt.Println(map1)

	var m2 Msg
	err = json.Unmarshal(m, &m2)
	fmt.Println(m2)
}

2、xml格式

encoding/xml可以从文件读取或者写入

xml.Unmarshal() //将xml文件解析成结构体
xml.Marshal()   //将结构体设置为xml字符串 
package main

import (
	"encoding/xml"
	"fmt"
	"strings"
)

var t, token xml.Token
var err error

func main() {
	input := "<Person><FirstName>Laura</FirstName><LastName>Lynn</LastName></Person>"
	inputReader := strings.NewReader(input)
	p := xml.NewDecoder(inputReader)

	for t, err = p.Token(); err == nil; t, err = p.Token() {
		switch token := t.(type) {
		case xml.StartElement:
			name := token.Name.Local
			fmt.Printf("Token name: %s\n", name)
			for _, attr := range token.Attr {
				attrName := attr.Name.Local
				attrValue := attr.Value
				fmt.Printf("An attribute is: %s %s\n", attrName, attrValue)
				// ...
			}
		case xml.EndElement:
			fmt.Println("End of token")
		case xml.CharData:
			content := string([]byte(token))
			fmt.Printf("This is the content: %v\n", content)
			// ...
		default:
			// ...
		}
	}
}

/**
输出:

Token name: Person
Token name: FirstName
This is the content: Laura
End of token
Token name: LastName
This is the content: Lynn
End of token
End of token
 */

3、Gob格式

Gob(Go binary) 是 Go 自己的以二进制形式序列化和反序列化程序数据的格式;只能go语言中使用。高效且简单。使用econding/gob进行编码和解码。文件中gob格式是二进制和文本的混合模式。 只有可导出的字段才会编码,默认值也会忽略;解析为结构体时,必须要匹配名称和可兼容类型才会被解析成功

       gob.NewEncoder(w io.Writer) *Encoder //返回一个encoder
       gob.NewDecoder(r io.Reader) *Decoder //返回一个reader
       (enc *Encoder) Encode(e interface{}) error //编码
       (dec *Decoder) Decode(e interface{}) error //解码,必须传入指针类型

编码:使用NewEncoder获取*Encoder,再使用Encoder调用Encode方法编码;
解码:使用NewDecoder获取*Decoder,再使用*Decoder调用Decode方法解码

4、msgpack格式

二进制的json数据格式:节省空间、性能好。使用go get -u github.com/vmihailenco/msgpack获取msgpack包

 msgpack.Marshal(v interface{})([]byte,err)
 msgpack.Unmarshal(data []byte,v inteface{})(err)
type Item struct {
    Foo string
}

b, err := msgpack.Marshal(&Item{Foo: "bar"})
if err != nil {
    panic(err)
}

var item Item
err = msgpack.Unmarshal(b, &item)
if err != nil {
    panic(err)
}
fmt.Println(item.Foo)//bar

5、protobuf格式

谷歌推出的二进制、基于代码自动生成的数据格式,性能好。使用IDL(接口描述语言)语言编写

安装protoc编译程序:https://github.com/protocolbuffers/protobuf/releases

安装golang代码插件:go get -u github.com/golang/protobuf/protoc-gen-go

使用命令 protoc --go_out=输出代码路径 proto文件路径生成代码

    protobuf编写流程:
       1、使用IDL接口描述语言编写proto文件   
       2、使用 protoc --go_out=. *.proto 生成go文件
       3、使用 github.com/golang/protobuf/proto的Marshal()和Unmarshal()方法来编码
//指定版本
syntax = "proto3";

//包名,protoc生成go文件的包名
package address;

//手机类型
//枚举类型,第一个字段值必须为0
enum PhoneType {
  HOME = 0;
  WOKR = 1;
}

//手机结构体,使用message关键字定义
message Phone {
  PhoneType type = 1; //表示对应到结构体的第一个字段,后面的数字表示标识号
  string number = 2;  //表示对应到结构体的第二个字段,以此类推
}


//人结构体
message Person {
   int32 id = 1;
   string name = 2;

   //repeated表示可重复,对应go中的切片
    repeated Phone phones = 3;
}

//联系人列表
message ContactBook {
   repeated Person persons = 1;
}