zoukankan      html  css  js  c++  java
  • 9.4 Go 数据格式

    9.4 Go 数据格式

    1.1. msgpack格式

    官方msgpack官网用一句话总结: It’s like JSON. but fast and small. 简单来讲,它的数据格式与json类似,但是在存储时对数字、多字节字符、数组等都做了很多优化,减少了无用的字符,二进制格式,也保证不用字符化带来额外的存储空间的增加。

    msgpack使用示例代码

    package main
    
    import (
        "fmt"
        "github.com/vmihailenco/msgpack"
        "io/ioutil"
        "math/rand"
    )
    
    type Person struct {
        Name string
        Age  int
        Sex  string
    }
    
    //写入json
    func writeJson(filename string) (err error) {
        var persons []*Person //切片,只能放入Person地址
        //生成10个结构体对象
        for i := 0; i < 100; i++ {
            p := &Person{
                Name: fmt.Sprintf("name%d", i),
                Age:  rand.Intn(100),
                Sex:  "Man",
            }
            //循环讲结构体放入切片
            persons = append(persons, p)
        }
        //序列化切片
        data, err := msgpack.Marshal(persons)
        if err != nil {
            fmt.Printf("=marshal failed, err:%v
    ", err)
            return
        }
        //写入序列化后的数据,到filename中
        err = ioutil.WriteFile(filename, data, 0755)
        if err != nil {
            fmt.Printf("write file failed, err:%v
    ", err)
            return
        }
    
        return
    }
    
    //读取json数据,传入文件参数
    func readJson(filename string) (err error) {
        var persons []*Person
        data, err := ioutil.ReadFile(filename)
        if err != nil {
            return
        }
    
        err = msgpack.Unmarshal(data, &persons)
        if err != nil {
            return
        }
    
        for _, v := range persons {
            fmt.Printf("%#v
    ", v)
        }
        return
    }
    
    func main() {
        filename := "./person.dat"
        err := writeJson(filename)
        if err != nil {
            fmt.Printf("write json failed, err:%v
    ", err)
            return
        }
    
        err = readJson(filename)
        if err != nil {
            fmt.Printf("read json failed, err:%v
    ", err)
            return
        }
    }
    

    json代码

    package main
    
    import (
        "encoding/json"
        "fmt"
        "io/ioutil"
        "math/rand"
    )
    
    type Person struct {
        Name string
        Age  int
        Sex  string
    }
    
    //写入json
    func writeJson(filename string) (err error) {
        var persons []*Person //切片,只能放入Person地址
        //生成10个结构体对象
        for i := 0; i < 100; i++ {
            p := &Person{
                Name: fmt.Sprintf("name%d", i),
                Age:  rand.Intn(100),
                Sex:  "Man",
            }
            //循环讲结构体放入切片
            persons = append(persons, p)
        }
        //序列化切片
        data, err := json.Marshal(persons)
        if err != nil {
            fmt.Printf("=marshal failed, err:%v
    ", err)
            return
        }
        //写入序列化后的数据,到filename中
        err = ioutil.WriteFile(filename, data, 0755)
        if err != nil {
            fmt.Printf("write file failed, err:%v
    ", err)
            return
        }
    
        return
    }
    
    //读取json数据,传入文件参数
    func readJson(filename string) (err error) {
        var persons []*Person
        data, err := ioutil.ReadFile(filename)
        if err != nil {
            return
        }
    
        err = json.Unmarshal(data, &persons)
        if err != nil {
            return
        }
    
        for _, v := range persons {
            fmt.Printf("%#v
    ", v)
        }
        return
    }
    
    func main() {
        filename := "./person.txt"
        err := writeJson(filename)
        if err != nil {
            fmt.Printf("write json failed, err:%v
    ", err)
            return
        }
    
        err = readJson(filename)
        if err != nil {
            fmt.Printf("read json failed, err:%v
    ", err)
            return
        }
    }
    

    Json包和msgpack包协议一样,区别:

    API的不同
    json.Marshal    
    json.Unmarshal
    
    msgpack.Marshal
    msgpack.Unmarshal
    
    msgpack占用传输更快
    yugoMBP:gobook yuchao$ ls -lh
    total 32
    -rw-r--r--  1 yuchao  staff   1.3K Mar 10 18:16 main.go
    -rwxr-xr-x  1 yuchao  staff   3.3K Mar 10 18:16 person.dat
    -rwxr-xr-x  1 yuchao  staff   3.8K Mar 10 18:16 person.txt
    

    1.2. protobuf数据交换格式

    什么是protobuf

    Protobuf(Protocol Buffer)是google 的一种数据交换的格式,它独立于语言,独立于平台。google 提供了多种语言的实现:java、c#、c++、go 和 python,每一种实现都包含了相应语言的编译器以及库文件。由于它是一种二进制的格式,比使用 xml 进行数据交换快许多。可以把它用于分布式应用之间的数据通信或者异构环境下的数据交换。作为一种效率和兼容性都很优秀的二进制数据传输格式,可以用于诸如网络传输、配置文件、数据存储等诸多领域。
    

    什么是protoc

    protoc是protobuf文件(.proto)的编译器,可以借助这个工具把 .proto 文件转译成各种编程语言对应的源码,包含数据类型定义、调用接口等。
    

    通过查看protoc的源码(参见github库)可以知道,protoc在设计上把protobuf和不同的语言解耦了,底层用c++来实现protobuf结构的存储,然后通过插件的形式来生成不同语言的源码。可以把protoc的编译过程分成简单的两个步骤(如上图所示):1)解析.proto文件,转译成protobuf的原生数据结构在内存中保存;2)把protobuf相关的数据结构传递给相应语言的编译插件,由插件负责根据接收到的protobuf原生结构渲染输出特定语言的模板。


    为什么用protobuf

    最近的项目中,一直使用Json做数据传输。Json用起来的确很方便。但相对于protobuf数据量更大些。做一个移动端应用,为用户省点流量还是很有必要的。正好也可以学习一下protobuf的使用
    
    跟Json相比protobuf性能更高,更加规范
    
    编解码速度快,数据体积小
    
    使用统一的规范,不用再担心大小写不同导致解析失败等蛋疼的问题了
    
    但也失去了一些便利性
    
    改动协议字段,需要重新生成文件。
    
    数据没有可读性
    

    介绍:

    Google推出的数据交换格式

    二进制

    代码自动生成

    宇宙最快格式

    开发流程:
    IDL编写
    生成指定语言的代码
    序列化-反序列化
    

    1.3. 安装protoc

    下载地址:

    https://github.com/protocolbuffers/protobuf/releases

    osx:https://github.com/protocolbuffers/protobuf/releases/download/v3.7.0/protoc-3.7.0-osx-x86_64.zip
    
    windows 64位:https://github.com/protocolbuffers/protobuf/releases/download/v3.7.0/protoc-3.7.0-win64.zip
    

    下载完毕后,配置protoc的PATH环境变量

    PATH="添加protoc的环境变量"
    

    1.4. 下载golang代码插件protoc-gen-go

    安装golang代码插件,如果下载出现问题,删除文件夹github.com/golang/protobuf重新下载
    go get -u github.com/golang/protobuf/protoc-gen-go
    go install github.com/golang/protobuf/protoc-gen-go
    

    添加protoc-gen-go命令到PATH变量中

    进入protobuf的文件夹,创建address文件夹
    mkdir address
    //生成go文件
    protoc --go_out=./address/ ./person.proto
    

    应用实例

    package main
    
    import (
        "fmt"
        "io/ioutil"
    
        "./address"
        "github.com/golang/protobuf/proto"
    )
    
    func writeProto(filename string) (err error) {
        var contactBook address.ContactBook
        for i := 0; i < 64; i++ {
            p := &address.Person{
                Id:   int32(i),
                Name: fmt.Sprintf("武%d", i),
            }
    
            phone := &address.Phone{
                Type:   address.PhoneType_HOME,
                Number: "15210858000",
            }
    
            p.Phones = append(p.Phones, phone)
            contactBook.Persons = append(contactBook.Persons, p)
        }
        //序列化protobuf数据
        data, err := proto.Marshal(&contactBook)
        if err != nil {
            fmt.Printf("marshal proto buf failed, err:%v
    ", err)
            return
        }
    
        err = ioutil.WriteFile(filename, data, 0755)
        if err != nil {
            fmt.Printf("write file failed, err:%v
    ", err)
            return
        }
        return
    }
    
    func readProto(filename string) (err error) {
        var contactBook address.ContactBook
        data, err := ioutil.ReadFile(filename)
        if err != nil {
            return
        }
        err = proto.Unmarshal(data, &contactBook)
        if err != nil {
            return
        }
    
        fmt.Printf("proto:%#v
    ", contactBook)
        return
    }
    
    func main() {
        filename := "./contactbook.dat"
        err := writeProto(filename)
        if err != nil {
            fmt.Printf("write proto failed, err:%v
    ", err)
            return
        }
        err = readProto(filename)
        if err != nil {
            fmt.Printf("read proto failed, err:%v
    ", err)
            return
        }
    }
    

  • 相关阅读:
    SAP MM 有了采购订单历史的PO行项目里的采购附加费不允许再改了?
    风之语.人在职场也需要'备胎'
    两万字,任正非采访全记录
    SAP 如何得到交货单上的序列号清单?
    【2019年版】如何向SAP公司提交Message?
    工作上996,生活上669,并不是什么难事儿!
    风之语.甲骨文裁员之我见
    天河2号-保持使用yhrun/srun时连接不中断 (screen 命令教程 )
    PXE 和 计算机网络启动
    Gmail 设置,时区
  • 原文地址:https://www.cnblogs.com/open-yang/p/11256930.html
Copyright © 2011-2022 走看看