-
Filed Number:范围 1- 2^29 - 1(536,870,911)排除19000 - 19999(供ProtoBuf内部使用)
-
用于数据保存时,同一个message中某些字段被删除,如果新增字段使用相同的Filed Number,会和已被删除的字段的Filed Number重复,使用reserved避免此问题
message Foo { reserved 2, 15, 9 to 11; reserved "foo", "bar"; }
-
singular:proto3默认设置,不需要显式设置
-
repeated:使用packed,减少数据量;将数据存储方式由Tag-Value,Tag-Value...变成Tag(WireType=2)-Length(Value总长度)-Value-Value-Value-Value...;proto3默认设置[packed = true],proto2默认没有[packed = true]
-
WireType:5(32-bit),是固定位数,没有msb,用于大于2^28的数据,因为Varint的int32每个字节有一位作为msb,只能存储小于等于2^28的数据,大于2^28用int64,反而占用更多字节;同理1(64-bit),用于大于2^56的数据。
-
未赋值的字段默认为默认值。
-
枚举:Proto3枚举类型第一个值必须是0;默认值为0;Proto2默认值为第一个值;
-
枚举类型可以使用 别名(alias) 定义相同的值;
enum EnumAllowingAlias { option allow_alias = true; UNKNOWN = 0; STARTED = 1; RUNNING = 1; }
- 嵌套类型复用:Message.SubMessage
- 嵌套message生成代码,增加一个中间类Types
message Foo {
message Bar {
}
}
namespace [...]
{
public sealed partial class Foo : IMessage<Foo>
{
public static partial class Types
{
public sealed partial class Bar : IMessage<Bar> { ... }
}
}
}
-
import public
// new.proto // All definitions are moved here
// old.proto // This is the proto that all clients are importing. 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
-
Oneof:多个字段共享一个内存,其中一个字段被赋值时,其他字段会被清空
-
map类型:对应代码中的Google.Protobuf.Collections.MapField<TKey, TValue>
map<key_type, value_type> map_field = N;
key_type: int、string;except:float point、bytes、enum
value_type:excpet maps
-
与Map类型等价
message MapFieldEntry { key_type key = 1; value_type value = 2; } repeated MapFieldEntry map_field = N;
-
Repeated Fields 对应代码中的Google.Protobuf.Collections.RepeatedField<T>
- package
package foo.bar; message Open { ... }
message Foo { ... foo.bar.Open open = 1; ... }
-
Any:在messageType中可以使用任意类型,比如代码中自定义类
import "google/protobuf/any.proto";
message ErrorStatus {
string message = 1;
repeated google.protobuf.Any details = 2;
}
// Storing an arbitrary message type in Any.
NetworkErrorDetails details = ...;
ErrorStatus status;
status.add_details()->PackFrom(details);
// Reading an arbitrary message from Any.
ErrorStatus status = ...;
for (const Any& detail : status.details()) {
if (detail.Is<NetworkErrorDetails>()) {
NetworkErrorDetails network_error;
detail.UnpackTo(&network_error);
... processing network_error ...
}
}
- Proto中的RPC:
- c#不支持生成service
service SearchService {
rpc Search (SearchRequest) returns (SearchResponse);
}