序列化工具proto3学习笔记

Posted on 2022-07-08 11:49  Capterlliar  阅读(279)  评论(0编辑  收藏  举报

此笔记基本在复述官方文档

1. .proto构成

syntax = "proto3";    //指定版本

message SearchRequest {
   //一下区域为field
  string query = 1;    //等号后面的是它的编号,不是值
  int32 page_number = 2;
  int32 result_per_page = 3;
}

定义好一个message,引用.proto,就可以在C++和Java里用啦。

关于field编号:省去解析字符串的烦恼,占用空间更小,范围为1~5e8,其中19000~19999不能用。

当一些message定义相同时,可以import其他.proto文件。import public a.proto意为此文件被引用时,a.proto也被引用。但java中不支持import public。

可以为一些message加package,避免命名冲突。引用的时候就像正常语言调用过来就好了。

2. field写法

required/optional/repeated + 数据类型 +「变量名」+ 「编号」

其中repeated由于历史原因编码很慢,需要加 [packed = true]

当optional的变量没有出现时,使用它的默认值,默认值的设置例如在末尾加 [default = 10]

注释格式:和C++一样

reserved:删掉的field编号。防止新版本已删除的编号在调用老版本时再次被使用,造成数据泄露等问题。

这里插一句message更新,更新直接改就行,旧版本会自动忽略新增内容,删除记得加关键字。

field内容可以为其他message。

extension字段:留给第三方插件的字段。

可以定义一个map,就是STL里类似的那个map。

3. Enum用法

当定义一个message的时候,有时我们希望其中一些field的值是规定的一系列值中的一个,这时我们用enum来列举可能的值,编号从0开始,例如:

message SearchRequest {
  required string query = 1;
  optional int32 page_number = 2;
  optional int32 result_per_page = 3 [default = 10];
  enum Corpus {
    UNIVERSAL = 0;
    WEB = 1;
    IMAGES = 2;
    LOCAL = 3;
    NEWS = 4;
    PRODUCTS = 5;
    VIDEO = 6;
  }
  optional Corpus corpus = 4 [default = UNIVERSAL];
}

当其值可以为其中多个的组合时,需要加上 option allow_alias = true;

保留值和上面差不多。

4. 嵌套使用

message里可以套message,当多一组数据不以message的形式存在时,可以用group。

5. Oneof用法

当一个message可能有多种数据构成时,每种可能的数据构成用Oneof来表示。多个Oneof在最终编码时只使用一个空间,也就是只能操作一个字段。

message SampleMessage {
  oneof test_oneof {
     string name = 4;
     SubMessage sub_message = 9;
  }
}

6. Services

要向别的服务器申请服务时调用,然后收发message。

7. Options

一些编译项,可能没作用,类似O2、O3这种。还有自定义选项,以后用到了再补充。

8. 编译使用

protoc --proto_path=IMPORT_PATH --cpp_out=DST_DIR --java_out=DST_DIR --python_out=DST_DIR path/to/file.proto
IMPORT_PATH:需要用.proto的目录