Go语言数据格式

1.数据交换格式简介

1.简介

  • 1.分布式系统
  • 2.打包和解包操做
  • 3.传输模式:
    • 1.网络传输
    • 2.API接口
    • 3.文件传输

2.JSON数据格式

1.对象{key-value}形式

2.数组[{key-value}]

3.实例代码

  • 1.Marshal:序列化
package main

import (
    "encoding/json"
    "fmt"
    "io/ioutil"
    "math/rand"
    "strconv"
)

type Person struct {
    Name string
    Age int
    Sex string
}
func writeJson(filename string) (err error) {
    var person []*Person
    for i := 0; i < 10; i++ {
	p := &Person{
  	    Name: "name" + strconv.Itoa(i),
	    Age:  rand.Intn(100),
	    Sex:  "Man",
	}
	person = append(person, p)
    }

    data, err := json.Marshal(person)
    if err != nil {
	fmt.Println("json marshal failed, err: ", err)
	return
    }
    ioutil.WriteFile(filename, data, 0755)
    return
}


func main()  {
    writeJson("./data.json")
}
  • 2.UnMarshal:反序列化
package main

import (
    "encoding/json"
    "fmt"
    "io/ioutil"
)

type Person struct {
    Name string
    Age int
    Sex string
}

func writeStruct(filename string) (err error) {
	data, err := ioutil.ReadFile(filename)
	if err != nil {
		fmt.Println("json unmarshal failed, err: ", err)
		return
	}
	var person []*Person
	json.Unmarshal(data, &person)
	fmt.Println(person)
	return
}

func main()  {
    writeStruct("./data.json")
}

3.XML数据格式

1.简介

  • 可扩展标记语言
  • 声明、根标签、子元素、属性

2.实例代码

<?xml version="1.0" encoding="UTF-8"?>
<dates version="1.0">
    <date>
        <id>1</id>
        <name>JSON</name>
        <abb>JavaScript Object Notation</abb>
    </date>
    <date>
        <id>2</id>
        <name>XML</name>
        <abb>eXtensible Markup Language</abb>
    </date>
    <date>
        <id>3</id>
        <name>YAML</name>
        <abb>Yet Another Markup Language</abb>
    </date>
</dates>
package main

import (
    "encoding/xml"
    "fmt"
    "io/ioutil"
)

type DateXml struct {
    Version string `xml:"version,attr"`
    Dates []Date `xml:"date"`
}

type Date struct {
    Id string `xml:"id"`
    Name string `xml:"name"`
    Abb string `xml:"abb"`
}

func writeStruct() (err error) {
    data, err := ioutil.ReadFile("./data.xml")
    if err != nil {
	fmt.Println("read xml failed, err: ", err)
	return
    }
    var dataStruct DateXml
    err = xml.Unmarshal(data, &dataStruct)
    if err != nil {
	fmt.Printf("unmarshal failed, err: %v", err)
    }
    fmt.Printf("%v", dataStruct)
    return
}
func main()  {
    writeStruct()
}

/*
{1.0 [{1 JSON JavaScript Object Notation} {2 XML eXtensible Markup Language} {3 YAML Yet Another Markup Language}]}
*/
  • 3.应用场景:配置文件以及webservice,比如:soap协议

4.MSGPack数据格式

1.二进制的json协议

  • 1.性能更快
  • 2.更省空间

2.应用实战

  • 1.Marshal:序列化
  • 2.UnMarshal:反序列化
  • 3.应用场景:Api通讯
  • 安装第三方包
go get github.com/vmihailenco/msgpack
package main

import (
    "fmt"
    "github.com/vmihailenco/msgpack/v5"
    "io/ioutil"
    "math/rand"
    "strconv"
)

type Person struct {
    Name string
    Age int
    Sex string
}
func writeJson(filename string) (err error) {
    var person []*Person
    for i := 0; i < 10; i++ {
	p := &Person{
	    Name: "name" + strconv.Itoa(i),
	    Age:  rand.Intn(100),
	    Sex:  "Man",
	}
	person = append(person, p)
    }

    data, err := msgpack.Marshal(person)
    if err != nil {
	fmt.Println("json marshal failed, err: ", err)
	return
    }
    ioutil.WriteFile(filename, data, 0755)
    return
}

func writeStruct(filename string) (err error) {
    data, err := ioutil.ReadFile(filename)
    if err != nil {
	fmt.Println("json unmarshal failed, err: ", err)
	return
    }
    var person []*Person
    msgpack.Unmarshal(data, &person)
    fmt.Println(person)
    return
}

func main()  {
    writeJson("./data.dat")
    //writeStruct("./data.dat")
}

5.Protobuf数据格式

1.简介

  • 1.google推出的数据交换格式
  • 2.二进制的
  • 3.基于代码自动生成

2.Protobuf开发流程

  • 1.IDL编写
  • 2.生成指定的语言代码
  • 3.序列化和反序列化

3.Protobuf数据类型

1.枚举类型
enum EnumAllowingAlias {
    UNKNOWN = 0;
    STARTED = 1;
    RUNNING = 2;
}
2.结构体类型
message Persion {
    // 后面的数字表示标识符
    int32  id = 1;
    string name = 2;
    // repeated 表示可以重复【数组】
    // 可以有多个手机
    repeated Phone phones = 3;
}

4.依赖安装

  • 1.地址:https://github.com/protocolbuffers/protobuf/releases
  • 2.安装protobuf编译器,解压后拷贝bin/protoc.exeGOPATH/bin目录下
  • 3.安装golang代码插件:go get -u github.com/golang/protobuf/protoc-gen-go

5.生成.proto文件

  • 1.编写IDLproto/person.proto
// 指定版本
// 注意:proto3与proto2的写法有些不同(proto3默认值为字段类型对应的零值,proto2需要使用default关键字来指明)
syntax = "proto3";

// 指定生成文件存储的路径,拼接`--go_out`指定的路径,即 ./address,和person.proto同级
option go_package = "/address";

// 指定等会文件生成出来的package
package address

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

// 手机
message Phone {
    // 类型 字段名
    PhoneType type = 1;
    string number = 2;
}

// 人
message Person {
    int32 id = 1;
    string name = 2;
    // required 消息体中必填字段,不设置会导致编码异常(require在proto3中不用写,默认)
    // optional 消息体中可选字段
    // repeated 消息体中可重复字段,重复的值的顺序会被保留,在go中重复的会被定义为切片
    repeated Phone phones = 3;
}

// 联系薄
message ConnectBook {
    repeated Person persons = 1;
}


// 定义服务
service SearchService {
    // rpc 服务的函数名 (传入参数—)  返回 (返回参数)
    rpc Search (SearchRequest) returns (SearchResponse);
}
  • 2.生成文件
protoc --go_out=. ./person.proto
  • 3.编写程序:proto/main.go
package main

import (
    "dcpuffer/dcpuffer/proto/address"
    "fmt"
    "github.com/golang/protobuf/proto"
    "io/ioutil"
)

func writeProto(filename string) (err error) {
    var connectBook address.ConnectBook
    for i := 0; i < 60; i++ {
	p := &address.Person{
	    Id:    int32(i),
	    Name:  fmt.Sprintf("刘%d", i),
	}
	phone := &address.Phone{
	    Type:   address.PhoneType_HOME,
	    Number: "15910827647",
	}
	p.Phones = append(p.Phones, phone)
	connectBook.Persons = append(connectBook.Persons, p)
    }
    data, err := proto.Marshal(&connectBook)
    if err != nil {
        fmt.Println("marshal proto buf failed, err: ", err)
	return
    }
    err = ioutil.WriteFile(filename, data, 0755)
    if err != nil {
	fmt.Println("write file failed, err: ", err)
	return
    }
    return
}

func readProto(filename string) (err error) {
    var connectBook address.ConnectBook
    data, _ := ioutil.ReadFile(filename)
    err = proto.Unmarshal(data, &connectBook)
    if err != nil {
	fmt.Println("read file failed, err: ", err)
    }
    fmt.Println(connectBook.String())
    return
}

func main()  {
    // 序列化
    //writeProto("./connectBook.dat")
    // 反序列化
    readProto("./connectBook.dat")
}
posted @ 2022-09-29 18:06  fatpuffer  阅读(117)  评论(0)    收藏  举报