proto(Protocol Buffers,简称 Protobuf)是 Google 开发的一种轻量级、高效的数据序列化格式,用于结构化数据的存储和传输。在 Protobuf 中,数据通过 .proto 文件定义,文件中包含消息类型(message types)和字段类型(field types)。

以下是 Protobuf 中支持的基本数据类型(标量类型,scalar types)的详细介绍:


Protobuf 的基本数据类型

类型 说明 对应 Go 的类型
double 双精度浮点数,64 位浮点数 float64
float 单精度浮点数,32 位浮点数 float32
int32 带符号的 32 位整数,变长编码(Varint)。适用于非负值较小的整数。 int32
int64 带符号的 64 位整数,变长编码(Varint)。适用于非负值较大的整数。 int64
uint32 无符号的 32 位整数,变长编码(Varint)。 uint32
uint64 无符号的 64 位整数,变长编码(Varint)。 uint64
sint32 带符号的 32 位整数,使用 ZigZag 编码的 Varint。适用于负值较多的场景。 int32
sint64 带符号的 64 位整数,使用 ZigZag 编码的 Varint。适用于负值较多的场景。 int64
fixed32 无符号的 32 位整数,固定长度编码。适用于值较大的整数。 uint32
fixed64 无符号的 64 位整数,固定长度编码。适用于值较大的整数。 uint64
sfixed32 带符号的 32 位整数,固定长度编码。 int32
sfixed64 带符号的 64 位整数,固定长度编码。 int64
bool 布尔值,truefalse bool
string UTF-8 编码的字符串,长度不能超过 2^32 string
bytes 任意二进制数据,长度不能超过 2^32 []byte

选择合适的数据类型

  1. 整数类型

    • 如果字段的值可能为负数,使用 int32int64
    • 如果字段的值始终为非负数,使用 uint32uint64
    • 对于可能包含负数的字段,如果负值较多,推荐使用 sint32sint64,因为它们使用 ZigZag 编码,能更高效地处理负数。
    • 对于值较大的整数,推荐使用 fixed32fixed64,因为它们的编码长度固定,能够避免 Varint 编码的开销。
  2. 浮点数类型

    • 对于需要高精度的浮点数,使用 double
    • 对于需要较少存储空间的浮点数,使用 float
  3. 布尔类型

    • 用于表示 truefalse
  4. 字符串和二进制数据

    • 使用 string 表示文本数据。
    • 使用 bytes 表示二进制数据。

示例 .proto 文件

syntax = "proto3";

package example;

message Person {
  string name = 1;          // 字符串
  int32 age = 2;           // 32 位整数
  double height = 3;       // 双精度浮点数
  bool is_student = 4;     // 布尔值
  repeated string hobbies = 5; // 字符串列表
  bytes avatar = 6;        // 二进制数据
}

注意事项

  1. 默认值

    • 如果字段未设置值,Protobuf 会使用默认值:
      • 数值类型:0
      • 布尔类型:false
      • 字符串类型:空字符串 ""
      • 二进制类型:空字节数组 []byte{}
      • 枚举类型:第一个枚举值(默认值为 0
  2. 字段编号

    • 每个字段必须有一个唯一的编号(从 1 开始)。
    • 字段编号用于标识字段,范围是 12^29 - 1,其中 1900019999 是保留值。
  3. 字段规则

    • optional:字段是可选的(默认行为)。
    • required:字段是必需的(不推荐使用,已被废弃)。
    • repeated:字段是一个列表。
  4. proto3proto2 的区别

    • proto3 是当前推荐使用的版本,简化了语法并移除了 required 字段。