1.基本概念

在 Protocol Buffers(protobuf)中,Wire Type 指的是在二进制序列化时,用来标识一个字段在 wire(网络传输或存储的字节流)中应该用什么方式编码的类型标识

它是 protobuf 二进制编码格式的核心组成部分,决定了数据的存储方式和解析规则。

每个 protobuf 字段在序列化时,会将其 字段编号(field number)wire type 组合成一个 key(也叫 tag),然后跟着 value。

key = (field_number << 3) | wire_type

这个 key 是一个 varint,其中:

  • 低 3 位(bit 0-2)存储 wire type
  • 高位(bit 3 及以上)存储 field number

2.类型表

Wire Type 含义 编码方式 对应的 protobuf 数据类型
0 Varint 变长整数编码 int32, int64, uint32, uint64, sint32, sint64, bool, enum
1 64-bit 固定 8 字节 fixed64, sfixed64, double
2 Length-delimited 长度前缀 + 数据 string, bytes, embedded messages, packed repeated fields
3 Start group 已废弃(deprecated) 用于 groups(protobuf 2 的废弃特性)
4 End group 已废弃(deprecated) 用于 groups
5 32-bit 固定 4 字节 fixed32, sfixed32, float

Groups 已废弃:wire type 3 和 4 是早期 protobuf 2 中用于支持“groups”的,现已被推荐使用嵌套消息代替,几乎不再使用。

3.举例说明

假设有如下 .proto 定义:

message Person {
  int32  id   = 1;   // wire type = 0 (Varint)
  string name = 2;   // wire type = 2 (Length-delimited)
  double score = 3;  // wire type = 1 (64-bit)
}

id = 12345name = "Alice"score = 98.6 时,二进制编码大致如下(简化):

# 字段 id (field_number=1, wire_type=0)
key = (1 << 3) | 0 = 0x08
value = 12345 的 varint 编码

# 字段 name (field_number=2, wire_type=2)
key = (2 << 3) | 2 = 0x12
length = 5
value = "Alice" 的 UTF-8 字节 (5 bytes)

# 字段 score (field_number=3, wire_type=1)
key = (3 << 3) | 1 = 0x19
value = 98.6 的 64-bit 固定长度编码 (8 bytes)

4.关键作用

作用 说明
解析时识别类型 解析器根据 wire type 知道该按 varint 还是固定长度还是带长度前缀来读取接下来的数据。
向后兼容 即使字段类型改变了(只要 wire type 兼容),新老版本仍可部分兼容。例如 int32uint32 都是 varint,可以互相解析。
空间效率 用 3 个 bit 标识类型,比在每个值前都加类型标记要高效得多。
跳过未知字段 解析器遇到未知 field number 时,可以根据 wire type 知道要跳过多少字节,从而忽略该字段。

5.兼容性

原始类型 可变更到的类型(兼容) 不兼容的类型
int32 / uint32 / int64 / uint64 bool, enum string, bytes, float, double
string / bytes 只能是 length-delimited 类型 varint / 固定长度类型
float / fixed32 fixed32 / sfixed32 varint / length-delimited
double / fixed64 fixed64 / sfixed64 varint / length-delimited

这就是为什么 protobuf 强调 “不要随意改变字段的 wire type”,否则老代码解析新数据时会失败。

6.一句话总结

Wire Type 是 protobuf 二进制编码中,用来标识字段在 wire 上采用哪种编码方式(varint、固定长度、或带长度前缀)的类型标识(低 3 位)。它决定了解析器如何读取该字段的值,是实现 protobuf 高效编码和向后兼容的关键机制。


参考

ProtoBuf 文档: Protocol Buffers 文档

Logo

汇聚全球AI编程工具,助力开发者即刻编程。

更多推荐