【Protobuf协议】002-标准类型、默认值、枚举、使用费其他消息类型

目录

三、标准类型

四、默认值

五、枚举

1、简单使用

2、别名

3、预留值

六、使用其他消息类型

1、简单例子

2、导入定义*

3、使用proto2消息类型


三、标准类型

其他语言见官方文档:https://developers.google.com/protocol-buffers/docs/javatutorial#scalar

.proto TypeNotesJava Type
double double
float float
int32使用可变长编码,编码负数的效率很低——如果你的字段可能有负数,使用sint32代替int
int64使用可变长编码,编码负数的效率很低——如果你的字段可能有负数,使用sint64代替long
uint32使用可变长度编码int[1]
uint64使用可变长度编码long[1]
sint32使用可变长编码,带符号的int值。它们比普通int32编码负数更有效int
sint64使用可变长编码,带符号的int值。它们比普通int64编码负数更有效long
fixed32总是4个字节,如果值经常大于2的28次方,则比uint32更有效int[1]
fixed64总是8个字节,如果值经常大于2的56次方,则比uint64更有效long[1]
sfixed32总是4个字节int
sfixed64总是8个字节long
bool boolean
string字符串必须始终包含UTF-8编码或7位ASCII文本,且长度不能超过2的32次方String
bytes可以包含不超过2的32次方的任意字节序列ByteString

 

四、默认值

在解析消息时,如果编码的消息不包含特定的单个元素,则解析对象中的相应字段将设置为该字段的默认值;

类型默认值
string空字符串
bytes空字符
boolfalse
num0
enums对于枚举,默认值是第一个定义的枚举值,该值必须为0
message与对应编程语言有关
重复字段重复字段的默认值为空(通常在适当的语言中为空列表)

请注意,对于标量消息字段(标准类型字段),一旦消息被解析,就无法判断字段是显式设置为默认值(例如,是否将布尔值设置为 false),还是根本没有设置,在定义消息类型时应该牢记这一点。例如,如果您不希望某些行为在默认情况下也发生,那么就不要设置一个布尔值,该布尔值在设置为 false 时可以开启某些行为。还要注意,如果将标量消息字段设置为默认值,则该值将不会在连接上序列化。

 

五、枚举

1、简单使用

限定字段的值在一个列表中;

在定义消息类型时,您可能希望它的某个字段只有一个预定义的值列表。比如某件商品几种确定的尺码,您可以非常简单地做到这一点,方法是在消息定义中为每个可能的值添加一个带常量的枚举。

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

如您所见,Corpus enum 的第一个常量映射为0,每个 enum 定义必须包含一个常量,该常量映射为0作为它的第一个元素。这是因为:

  • 必须有一个0值,以便我们可以使用0作为数值默认值;

  • 0值必须是第一个元素,以便与 proto2语义兼容,其中第一个枚举值总是默认值。

枚举数常数必须在32位整数的范围内。由于枚举值在线路上使用变容编码,因此负值效率低,因此不推荐使用。可以在消息定义中定义枚举(如上面的例子所示) ,也可以在消息定义中重用这些枚举。

如果在.proto文件中使用枚举,在使用protobuf编译器编译之后,会生成C++、Java对应的枚举,Python有一个特殊的EnumDescriptor类;

警告:生成的代码可能会受到特定于语言的枚举数量限制;

 

2、别名

假如你需要给不同的枚举常量设置为相同的值,那么你必须设置别名,这样做必须将 allow_alias 选项设置为 true ,否则会报错!

 

message MyMessage1 {
  enum EnumAllowingAlias {
    option allow_alias = true;
    UNKNOWN = 0;
    STARTED = 1;
    RUNNING = 1;
  }
}
message MyMessage2 {
  enum EnumNotAllowingAlias {
    UNKNOWN = 0;
    STARTED = 1;
    // RUNNING = 1;  // Uncommenting this line will cause a compile error inside Google and a warning message outside.
  }
}

 

3、预留值

与预留字段类似;

enum Foo {
    reserved 2, 15, 9 to 11, 40 to max;
    reserved "FOO", "BAR";
}

注意,不能在同一保留语句中混合字段名和数值。

 

六、使用其他消息类型

1、简单例子

message SearchResponse {
    repeated Result results = 1;
}

message Result {
    string url = 1;
    string title = 2;
    repeated string snippets = 3;
}

 

2、导入定义*

这个部分不太明白!!!

注意,这个特性在Java中是不可用的!

上面的例子中,Result消息和SearchResponse消息定义在同一个文件中,可以直接使用,如果想要使用其他 .proto 文件中定义的消息,可以将这些文件导入!

import "myproject/other_protos.proto";

默认情况下你只能使用直接导入的 .proto 文件中的定义,然而,有时候你需要移动一个 .proto 文件到一个新的位置,可以不直接移动 .proto 文件,只需放入一个伪 .proto 文件在老的位置,然后使用import public转向新的位置。import public 依赖性会通过任意导入包含import public声明的proto文件传递。例如:

// new.proto
// All definitions are moved here
// old.proto
// This is the proto that all clients are importing.
// 这是所有客户端正在导入的proto
import public "new.proto";
import "other.proto";
// client.proto
import "old.proto";
// You use definitions from old.proto and new.proto, but not other.proto
// 你可以使用来自new.proto的和old.proto的定义,而不是other.proto

通过在编译器命令行参数中使用-I/--proto_pathprotocal 编译器会在指定目录搜索要导入的文件。如果没有给出标志,编译器会搜索编译命令被调用的目录。通常你只要指定proto_path标志为你的工程根目录就好,并且指定好导入的正确名称就好。

 

3、使用proto2消息类型

在你的proto3消息中导入proto2的消息类型也是可以的,反之亦然,然后proto2枚举不可以直接在proto3的标识符中使用(如果仅仅在proto2消息中使用是可以的);

 

 

 

 

 

 

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值