Protocol Buffers详解

potocol Buffers (简称 protobuf) 是 Google 开发的一种高效的数据序列化格式,用于结构化数据的序列化、反序列化和传输。以下是 protobuf 的全面解析:

核心特性

  • 跨语言支持:支持 C++, Java, Python, Go, C#, Ruby 等多种语言
  • 高效二进制格式:比 XML/JSON 更小、更快
  • 强类型接口:通过 .proto 文件定义数据结构
  • 向后兼容:支持字段扩展而不破坏旧代码
  • 代码生成:通过编译器生成数据访问类

字段规则

  • singular: 单数字段(proto3默认)
  • repeated: 数组/列表字段
  • map<K,V>: 映射表字段(proto3特有)
  • oneof: 互斥字段组(同一时间只能设置其中一个)
  • optional: 可选
  • required: 表示必须赋值,否则序列化会失败(proto3 已移除此修饰符,需确保调用方赋值)。-》在 proto3 中,所有字段默认为 optional,建议通过业务逻辑强制校验必填字段,而非依赖协议
  • Protocol Buffers C++ API 中,repeated 字段通常提供以下方法:如下为消息定义:
  • des_relation_size() → 获取列表大小(类似 std::vector::size())。
  • des_relation(i) → 获取第 i 个元素(索引从 0 开始)。
  • add_des_relation() → 添加一个新元素(返回可修改的引用)。

成员变量访问语法

1、修改:set_<field_name>()

  1. 2、访问字段: <field_name>()

3、成员是否存在:has_<field_name>()

4、获取 repeated/map 字段长度

5、检查字符串字段是否为空.empty()

session_info.audio_media_info().peer_key().empty()

安全注意事项

  1. 无需检查嵌套消息是否存在
    • 即使 audio_media_info 未设置,audio_media_info() 也会返回有效(但空)的默认消息,不会引发空指针异常
    • 直接调用 peer_key().empty() 是安全的。
  2. 与 has_...() 的区别
    • 如果需要区分"字段未设置"和"显式设置为空",需使用 has_audio_media_info()(仅 proto2 或 proto3 的 optional 字段支持):
bool is_explicitly_empty = session_info.has_audio_media_info() && session_info.audio_media_info().peer_key().empty();

6、获取字符串字段长度 .size()

size_t key_length = session_info.audio_media_info().peer_key().size();

  1. 与 empty() 的关系
    • peer_key().size() == 0 等价于 peer_key().empty(),但语义更明确(显式检查长度)。 

7、获取字符串字段的底层字符数组(C 风格字符串).data()

const char* key_data = session_info.audio_media_info().peer_key().data();

data()

调用 std::string::data(),返回指向字符串内容的 const char*(C 风格字符串)。

C++11 起:保证以 \0 结尾(等同于 c_str())。

C++11 前:不一定以 \0 结尾,需结合 size() 使用。

8、默认值处理

proto3 中未设置的字段会返回类型默认值:

数字类型:0

布尔类型:false

字符串:空字符串 ""

嵌套消息:null(语言相关)

9、数据类型

10、关键注意事项

  1. proto2 vs proto3
    • has 方法在 proto3 中仅对 optional 或消息字段有效。
  2. 性能优化
    • 对 repeated 字段预分配空间(C++):

msg.mutable_des_media_session_id()->Reserve(100);

  1. 线程安全
    • Protobuf 对象非线程安全修改时需加锁。

11、版本差异: proto2 vs proto3

使用流程

  1. 编写 .proto 文件定义数据结构
  2. 使用 protoc 编译器生成代码:

protoc --cpp_out=. example.proto

protoc --java_out=. example.proto

3、在代码中使用生成的类:

适用场景

局限性

最佳实践

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值