grpc-go Proto3语法(二) - Go语言中文社区

grpc-go Proto3语法(二)


  1. syntax = "proto3";
    文件的第一行指定了你使用的是proto3的语法:如果你不指定,protocol buffer 编译器就会认为你使用的是proto2的语法。这个语句必须出现在.proto文件的非空非注释的第一行。

  2. message SearchRequest {......}
    message 定义实体

  3. 基本数据类型

    image
  4. 注释符号: 双斜线,如://xxxxxxxxxxxxxxxxxxx

  5. 字段唯一数字标识(用于在二进制格式中识别各个字段,上线后不宜再变动):Tags
    1到15使用一个字节来编码,包括标识数字和字段类型(你可以在Protocol Buffer 编码中查看更多详细);16到2047占用两个字节。因此定义proto文件时应该保留1到15,用作出现最频繁的消息类型的标识。记得为将来会继续增加并可能频繁出现的元素留一点儿标识区间,也就是说,不要一下子把1—15全部用完,为将来留一点儿。
    标识数字的合法范围:最小是1,最大是 229 - 1,或者536,870,911。
    另外,不能使用19000 到 19999之间的数字(FieldDescriptor::kFirstReservedNumber through FieldDescriptor::kLastReservedNumber),因为它们被Protocol Buffers保留使用

  6. 字段修饰符:
    required:值不可为空
    optional:可选字段
    singular:符合语法规则的消息包含零个或者一个这样的字段(最多一个)
    repeated:(我把它理解为数组)一个字段在合法的消息中可以重复出现一定次数(包括零次)。重复出现的值的次序将被保留。在proto3中,重复出现的值类型字段默认采用压缩编码。你可以在这里找到更多关于压缩编码的东西: Protocol Buffer Encoding
    默认值: optional PhoneType type = 2 [default = HOME];

  7. 代理类生成

    1. C++, 每一个.proto 文件可以生成一个 .h 文件和一个 .cc 文件
    2. Java, 每一个.proto文件可以生成一个 .java 文件
    3. Python, 每一个.proto文件生成一个模块,其中为每一个消息类型生成一个静态的描述器,在运行时,和一个metaclass一起使用来创建必要的Python数据访问类
    4. Go, 每一个.proto生成一个 .pb.go 文件
    5. Ruby, 每一个.proto生成一个 .rb 文件
    6. Objective-C, 每一个.proto 文件可以生成一个 pbobjc.h 和一个pbobjc.m 文件
    7. C#, 每一个.proto文件可以生成一个.cs文件.
  8. 字段默认值

    1. strings, 默认值是空字符串(empty string)
    2. bytes, 默认值是空bytes(empty bytes)
    3. bools, 默认值是false
    4. numeric, 默认值是0
    5. enums, 默认值是第一个枚举值(value必须为0)
    6. message fields, the field is not set. Its exact value is langauge-dependent. See the generated code guide for details.
    7. repeated fields,默认值为empty,通常是一个空list
  9. 枚举


    image

    第一个元素的value必须为0;

  10. Maps字段类型:map<key_type, value_type> map_field = N;

    1. map字段不能是repeated.
    2. Wire format ordering and map iteration ordering of map values is undefined, so you cannot rely on your map items being in a particular order.
    3. When generating text format for a .proto, maps are sorted by key. Numeric keys are sorted numerically.
    4. When parsing from the wire or when merging, if there are duplicate map keys the last key seen is used. When parsing a map from text format, parsing will fail if there are duplicate keys.
  11. 更新.proto文件
    当原有的.proto结构不能满足业务需求时,可以修改.proto文件,重新生成代理类,修改时需遵循以下原则:

    1. 不能修改已存在字段的唯一数字标识符(tags)
    2. If you add new fields, any messages serialized by code using your "old" message format can still be parsed by your new generated code. You should keep in mind the default values for these elements so that new code can properly interact with messages generated by old code. Similarly, messages created by your new code can be parsed by your old code: old binaries simply ignore the new field when parsing. Note that unknown fields are discarded when the message is deserialized, so if the message is passed on to new code, the new fields will not still be available (this is different behaviour to proto2, where unknown fields are serialized along with the message).
    3. 对废弃的字段,它的tags不能被再次使用,可以不删除,而是给字段添加“OBSOLETE_ ”前缀,这样可以避免将来重新使用这个tags
    4. int32, uint32, int64, uint64, 和bool是完全兼容的,这些字段类型之间可以直接修改
    5. sint32 和 sint64 是兼容的,但是和其他的数字类型不兼容
    6. string 和 bytes 是兼容的,由于bytes也是 UTF-8格式
    7. Embedded messages are compatible with bytes if the bytes contain an encoded version of the message.
    8. fixed32 和 sfixed32兼容, fixed64和sfixed64兼容
    9. enum 和 int32, uint32, int64, and uint64 in terms of wire format (note that values will be truncated if they don't fit). However be aware that client code may treat them differently when the message is deserialized: for example, unrecognized proto3 enum types will be preserved in the message, but how this is represented when the message is deserialized is language-dependent. Int fields always just preserve their value.
  12. Packages支持

  13. 定义Services

  14. 其他Options:

    1. java_package(file option):option java_package = "com.example.foo";
    2. java_outer_classname(file option ):option java_outer_classname = "Ponycopter";
    3. optimize_for(file option ):值为SPEED, CODE_SIZE或LITE_RUNTIME;如:option optimize_for = CODE_SIZE;
        • SPEED (default): The protocol buffer compiler will generate code for serializing, parsing, and performing other common operations on your message types. This code is extremely highly optimized.
        • CODE_SIZE: The protocol buffer compiler will generate minimal classes and will rely on shared, reflection-based code to implement serialialization, parsing, and various other operations. The generated code will thus be much smaller than with SPEED, but operations will be slower. Classes will still implement exactly the same public API as they do in SPEED mode. This mode is most useful in apps that contain a very large number .proto files and do not need all of them to be blindingly fast.
        • LITE_RUNTIME: The protocol buffer compiler will gener ate classes that depend only on the "lite" runtime library (libprotobuf-lite instead of libprotobuf). The lite runtime is much smaller than the full library (around an order of magnitude smaller) but omits certain features like descriptors and reflection. This is particularly useful for apps running on constrained platforms like mobile phones. The compiler will still generate fast implementations of all methods as it does in SPEED mode. Generated classes will only implement the MessageLite interface in each language, which provides only a subset of the methods of the full Message interface.
    4. cc_enable_arenas (file option ): 生成C++代码时启用arena allocation.
    5. objc_class_prefix (file option ): 设置 Objective-C class前缀,which is prepended to all Objective-C generated classes and enums from this .proto. There is no default. You should use prefixes that are between 3-5 uppercase characters as recommended by Apple. Note that all 2 letter prefixes are reserved by Apple.
    6. deprecated (field option): 如果设置为true,则该字段被置为“deprecated”,在新的代码中不能被继续使用,In most languages this has no actual effect. In Java, this becomes a @Deprecated annotation. In the future, other language-specific code generators may generate deprecation annotations on the field's accessors, which will in turn cause a warning to be emitted when compiling code which attempts to use the field. If the field is not used by anyone and you want to prevent new users from using it, consider replacing the field declaration with a reserved statement.
      int32 old_field = 6 [deprecated=true];
      示例:
image
版权声明:本文来源简书,感谢博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明。
原文链接:https://www.jianshu.com/p/ec59040a645e
站方申明:本站部分内容来自社区用户分享,若涉及侵权,请联系站方删除。
  • 发表于 2020-02-02 14:55:47
  • 阅读 ( 1611 )
  • 分类:Go

0 条评论

请先 登录 后评论

官方社群

GO教程

猜你喜欢