云海的博客
首页
  • 接口
  • 数组
  • slice
  • map
  • 指针
  • 反射
  • Context
  • sync.map
  • 锁
  • 类型和类型指针分析
  • recover
  • 从零实现RPC框架
  • make和new区别
  • channel
  • sync.Once
  • sync.Pool
  • protobuf
  • MongoDB pkg源码-findone
  • MyBatis
  • Maven
  • 解析Laravel框架—路由处理
  • PHP(客户端)与 Golang(服务端)使用grpc+protobuf 通信
  • JAVA(客户端)与 Golang(服务端) 使用grpc+protobuf通信
  • Docker使用笔记-常用命令
  • Docker使用笔记-容器间通讯
  • Docker使用笔记-搭建Redis集群
  • Docker使用笔记-镜像多阶段构建
  • Kubernetes部署golang服务
  • Linux常用命令
  • Docker安装Prometheus与Grafana
  • Protobuf
  • TCP抓包
  • 概述-《TCP/IP详解》读书笔记
  • 索引
  • 事务隔离级别
  • 常识
  • 每日一题(1)
  • 每日一题(2)
  • 每日一题(3)
  • 每日一题(4)
关于
GitHub (opens new window)

云海

服务端研发
首页
  • 接口
  • 数组
  • slice
  • map
  • 指针
  • 反射
  • Context
  • sync.map
  • 锁
  • 类型和类型指针分析
  • recover
  • 从零实现RPC框架
  • make和new区别
  • channel
  • sync.Once
  • sync.Pool
  • protobuf
  • MongoDB pkg源码-findone
  • MyBatis
  • Maven
  • 解析Laravel框架—路由处理
  • PHP(客户端)与 Golang(服务端)使用grpc+protobuf 通信
  • JAVA(客户端)与 Golang(服务端) 使用grpc+protobuf通信
  • Docker使用笔记-常用命令
  • Docker使用笔记-容器间通讯
  • Docker使用笔记-搭建Redis集群
  • Docker使用笔记-镜像多阶段构建
  • Kubernetes部署golang服务
  • Linux常用命令
  • Docker安装Prometheus与Grafana
  • Protobuf
  • TCP抓包
  • 概述-《TCP/IP详解》读书笔记
  • 索引
  • 事务隔离级别
  • 常识
  • 每日一题(1)
  • 每日一题(2)
  • 每日一题(3)
  • 每日一题(4)
关于
GitHub (opens new window)
  • Docker使用笔记-常用命令
  • Docker使用笔记-镜像多阶段构建
  • Docker使用笔记-搭建Redis集群
  • Docker使用笔记-容器间通讯
  • Kubernetes部署golang服务
  • Linux命令
  • 网关浅析
  • Nginx配置
  • Protobuf
    • Docker安装Prometheus与Grafana
    • EFK日志收集系统单机版
    • 微服务
    云海
    2022-06-11
    目录

    Protobuf

    # 概述

    本文根据官方文档,整理而成。

    # 示例

    syntax = "proto3";
    
    message SearchRequest {
        string query = 1;
        int32 page_num = 2;
        int32 results_per_page = 3;
    }
    
    1
    2
    3
    4
    5
    6
    7
    • 第一行需声明proto版本,如果不声明,默认当proto2处理。
    • The SearchRequest message definition specifies three fields (name/value pairs), one for each piece of data that you want to include in this type of message. Each field has a name and a type.

    # 指定字段类型

    在之前的例子中, 它们的字段都是单一类型: two integers (page_number and results_per_page) and a string (query). You can also specify enumerations and composite types like other message types for your field.

    # 分配字段编号

    You must give each field in your message definition a number between 1 and 536,870,911 with the following restrictions:

    • 给定的数字在该消息的所有字段中必须是唯一的.
    • 字段号19,000到19999是为协议缓冲区实现保留的。如果您在消息中使用这些保留字段号之一,协议缓冲区编译器将报错。

    一旦使用了消息类型,就不能更改此号码,因为它标识了消息连接格式中的字段。

    # 重复使用字段编号的后果

    Reusing a field number makes decoding wire-format messages ambiguous.

    # 指定字段标签

    • optional:可选字段处于两种可能状态之一。
    • repeated:此字段类型可以在格式良好的消息中重复0次或多次。重复值的顺序将被保留。(数组)
    • map:this is a paired key/value field type.
    • 如果未显示指定标签,则使用默认标签。在 proto3 语法中,如果不指定修饰类型,默认值为 singular. singular: 表示被修饰的字段最多出现 1次,即出现 0次或 1次。

    # 添加更多的消息类型

    可以在单个.proto文件中定义多个消息类型。这在定义多个相关消息时非常有用,例如,如果希望定义与SearchRequest消息类型对应的回复消息格式,则可以将其添加到相同的.proto中。

    syntax="proto3";
    
    message SearchRequest {
      string query = 1;
      int32 page_number = 2;
      int32 results_per_page = 3;
    }
    
    message SearchResponse {
     ...
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11

    # 添加注解

    To add comments to your .proto files, use C/C++-style // and /* ... */ syntax.

    # 删除字段

    如果操作不当,删除字段可能会导致严重的问题。

    # Reserved字段

    如果您通过完全删除一个字段或将其注释掉来更新消息类型,那么将来的开发人员可以在对该类型进行更新时重用该字段号。这可能导致严重的问题,如重用字段号的后果中所述。 为了确保不会发生这种情况,请将已删除的字段号添加到保留列表中。为了确保消息的JSON和TextFormat实例仍然可以被解析,还要将删除的字段名称添加到保留列表中。 如果将来的开发人员试图使用这些保留的字段号或名称,协议缓冲区编译器将会报错。

    message Foo {
      reserved 2, 15, 9 to 11;
      reserved "foo", "bar";
    }
    
    1
    2
    3
    4

    保留字段的取值范围是包含的(9 ~ 11与9、10、11相同)。注意,不能在同一保留语句中混合使用字段名和字段号。

    # 值类型

    .proto
    Type
    Java
    Type
    Go
    Type
    PHP
    Type
    double double float64 float
    float float float32 float
    int32 int int32 integer
    int64 long int64 integer
    uint32 int uint32 integer
    uint64 long uint64 integer
    bool boolean bool boolean
    string string string string
    bytes ByteString []byte string

    # 默认值

    • string 默认值为空字符串
    • bytes 默认值为空的字节数组
    • bool 默认值为false
    • 数值类型 默认值为0
    • For enums, the default value is the first defined enum value, which must be 0.

    # 枚举类型

    在定义消息类型时,您可能希望其中一个字段只具有预定义值列表中的一个。例如,假设您想为每个SearchRequest添加一个语料库字段,其中语料库可以是UNIVERSAL、WEB、IMAGES、LOCAL、NEWS、PRODUCTS或VIDEO。只需在消息定义中添加一个枚举,并为每个可能的值添加一个常量,就可以非常简单地做到这一点。 在下面的示例中,我们添加了一个名为Corpus的枚举,其中包含所有可能的值,以及一个类型为Corpus的字段:

    enum Corpus {
      CORPUS_UNSPECIFIED = 0;
      CORPUS_UNIVERSAL = 1;
      CORPUS_WEB = 2;
      CORPUS_IMAGES = 3;
      CORPUS_LOCAL = 4;
      CORPUS_NEWS = 5;
      CORPUS_PRODUCTS = 6;
      CORPUS_VIDEO = 7;
    }
    
    message SearchRequest {
      string query = 1;
      int32 page_number = 2;
      int32 results_per_page = 3;
      Corpus corpus = 4;
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17

    正如你所看到的,Corpus枚举的第一个常量映射到0:每个枚举定义必须包含一个映射到0的常量作为其第一个元素。这是因为:

    • 必须有一个零值,以便我们可以使用0作为数字默认值。
    • 为了与proto2语义兼容,零值需要是第一个元素,在proto2语义中,第一个枚举值总是默认值。

    可以通过将相同的值赋给不同的枚举常量来定义别名。为此,您需要将allow_alias选项设置为true,否则,当找到别名时,协议编译器会生成一条警告消息。虽然所有别名值在反序列化期间都是有效的,但序列化时总是使用第一个值。

    enum EnumAllowingAlias {
      option allow_alias = true;
      EAA_UNSPECIFIED = 0;
      EAA_STARTED = 1;
      EAA_RUNNING = 1;
      EAA_FINISHED = 2;
    }
    
    enum EnumNotAllowingAlias {
      ENAA_UNSPECIFIED = 0;
      ENAA_STARTED = 1;
      // ENAA_RUNNING = 1;  // Uncommenting this line will cause a warning message.
      ENAA_FINISHED = 2;
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14

    Enumerator constants must be in the range of a 32-bit integer.

    # 使用其他消息类型

    您可以使用其他消息类型作为字段类型。例如,假设您希望在每个SearchResponse消息中包含Result消息,那么您可以在相同的.proto中定义Result消息类型,然后在SearchResponse中指定Result类型的字段.

    message SearchResponse {
      repeated Result results = 1;
    }
    
    message Result {
      string url = 1;
      string title = 2;
      repeated string snippets = 3;
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9

    # Importing Definitions

    import "myproject/other_protos.proto";
    
    1

    # 嵌套类型

    您可以在其他消息类型中定义和使用消息类型,如下面的示例所示,Result消息在SearchResponse消息中定义。

    message SearchResponse {
      message Result {
        string url = 1;
        string title = 2;
        repeated string snippets = 3;
      }
      repeated Result results = 1;
    }
    
    1
    2
    3
    4
    5
    6
    7
    8

    # Any类型

    要使用Any类型,您需要导入Google/protobuf/any.proto。

    import "google/protobuf/any.proto";
    
    message ErrorStatus {
      string message = 1;
      repeated google.protobuf.Any details = 2;
    }
    
    1
    2
    3
    4
    5
    6

    # Packages

    您可以向.proto文件添加一个package说明符,以防止协议消息类型之间的名称冲突。

    package foo.bar;
    message Open { ... }
    
    1
    2

    然后,您可以在定义消息类型的字段时使用package说明符.

    message Foo {
      ...
      foo.bar.Open open = 1;
      ...
    }
    
    1
    2
    3
    4
    5

    每种编程语言中,package说明符是不同的。

    • In Java and Kotlin, the package is used as the Java package, unless you explicitly provide an option java_package in your .proto file.
    • In Go, the package is used as the Go package name, unless you explicitly provide an option go_package in your .proto file.
    上次更新: 2023/10/07
    Nginx配置
    Docker安装Prometheus与Grafana

    ← Nginx配置 Docker安装Prometheus与Grafana→

    最近更新
    01
    函数
    04-11
    02
    面试题
    04-11
    03
    EFK日志收集系统单机版
    08-18
    更多文章>
    Theme by Vdoing | Copyright © 2022-2025 Evan Xu | MIT License
    • 跟随系统
    • 浅色模式
    • 深色模式
    • 阅读模式