json

JSON是一种更轻量级的基于文本的编码方式,经常用在client/server端的通讯中。

yaml

YAML类似JSON,新的特性更强大,更适合人类阅读,也更紧凑。

yaml支持的数据结构有三种:

  1. 对象:键值对的集合,又称为映射(mapping)/ 哈希(hashes) / 字典(dictionary)
  2. 数组:一组按次序排列的值,又称为序列(sequence) / 列表(list)
  3. 纯量(scalars):单个的、不可再分的值。字符串、布尔值、整数、浮点数、Null、时间、日期

protobuf

Protobuf终极教程

  • Protocol Buffer (简称Protobuf) 是 Google 出品的性能优异、跨语言、跨平台的序列化库
  • protoc 是 protobuf 文件(.proto)的编译器(参考链接),可以借助这个工具把 .proto 文件转译成各种编程语言对应的源码,包含数据类型定义、调用接口等。
  • protoc-gen-go 是生成.go文件的插件,配合 protoc –go_out=output_directory input_diretory/*.proto

tip: 如果 google.golang.org/protobuf 为 v1.25.0,因此 protoc-gen-go 也应同步版本为 v1.25.0。

最近的项目中,一直使用Json做数据传输。Json用起来的确很方便。但相对于protobuf数据量更大些。做一个移动端应用,为用户省点流量还是很有必要的。

protobuf优点

  • 性能更高,更加规范
  • 编解码速度快,数据体积小
  • 使用统一的规范,不用再担心大小写不同导致解析失败等蛋疼的问题了

protobuf缺点

  • 改动协议字段,需要重新生成文件。
  • 数据没有可读性

安装 protobuf

  1. 安装 protoc 编译器

    protoc –version # 查询系统 protobuf 编译器的版本号

    方式一: macos => brew install protobuf

    方式二:(可指定版本,优先选择这个方案)

    • https://github.com/protocolbuffers/protobuf/releases 选择下载最新的 protoc-21.2-osx-x86_64.zip

    • 安装

      • m1版本: protoc-21.2-osx-aarch_64.zip
      • x86版本: protoc-21.2-osx-x86_64.zip
      1
      
      unzip protoc-21.2-osx-x86_64.zip && sudo cp -r include/ /usr/local/include/ && sudo cp -r bin/ /usr/local/bin/
      
  2. 安装编译器插件 protoc-gen-go (protoc-gen-go用于生成Go语言代码)

    protoc-gen-go 的版本号,可以在生成的 xxx.pb.go 文件开头查看

    1
    2
    
    go get -u google.golang.org/protobuf/cmd/protoc-gen-go@v1.23.0
    或者 go get -u github.com/golang/protobuf/protoc-gen-go@v1.3.2
    
  3. 编译 .proto 文件

    1
    2
    3
    
    protoc --proto_path=../convention --go_out=../convention/. ../convention/protobuf/*.proto # --proto_path=PATH:它表示的是我们要在哪个路径下搜索.proto文件;--go_out=PATH:编程语言插件参数
    rm -rf lib/pb/* && mkdir -p lib/pb && mv ../convention/protobuf/*.go lib/pb/
    cp ../convention/protocol/*.go lib/pb/
    

数据类型

  • repeated xxx: 数组,repeated string snippets = 3;

  • enum: 枚举值,转成 go 后变成常量定义和生成对应的枚举值map映射

    1
    2
    3
    4
    5
    6
    7
    
        enum Event {
            web = 0; // web 事件
            web_login = 1;  // web登陆
            web_logout = 2; // web登出
        }
    
        pb.Event_web_login.String() // 输出web_login:获取枚举值1对应的key名
    
  • map<int64,string> values = 1;

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    
    # 结构体嵌套用法
    message  GetJsapiTicketResp {
        message JsapiTicket {
            string corp_id = 1;
            string noncestr = 2;
            int64 timestamp = 3;
            string signature = 4;
        }
        JsapiTicket corp_jsapi_ticket = 1;
        JsapiTicket app_jsapi_ticket = 2;
    }
    

分配字段编号

每个消息定义中的每个字段都有唯一的编号。这些字段编号用于标识消息二进制格式中的字段,并且在使用消息类型后不应更改。请注意,范围 1 到 15 中的字段编号需要一个字节进行编码,包括字段编号和字段类型(具体原因见 Protocol Buffer 编码原理 这一章节)。范围 16 至 2047 中的字段编号需要两个字节。所以你应该保留数字 1 到 15 作为非常频繁出现的消息元素。请记住为将来可能添加的频繁出现的元素留出一些空间。

可以指定的最小字段编号为1,最大字段编号为2^29^-1 或 536,870,911。也不能使用数字 19000 到 19999(FieldDescriptor :: kFirstReservedNumber 到 FieldDescriptor :: kLastReservedNumber),因为它们是为 Protocol Buffers实现保留的。

如果在 .proto 中使用这些保留数字中的一个,Protocol Buffers 编译的时候会报错。

1
2
3
4
5
6
7
syntax = "proto3";

message SearchRequest {
  string query = 1;
  int32 page_number = 2;
  int32 result_per_page = 3;
}