CHUAN2 DEV ENGINE
996 正版授权研发中心 · 360 授权合作教学中心 · 抖音传奇直播合作授权 · 快手推广运营商授权
OFFICIAL LICENSED ACADEMY 查验官方授权证书 →
// 威海旷世互娱教学基地 · 技术文章
网络通信框架设计

【网络通信】Protobuf schema 设计:oneof、optional 与兼容取舍

2026-09-20 08:45 作者:996 技术组 1 阅读 996引擎Lua教程传奇脚本
完整课程入口:996 全套课程体系Lua 学习路径幂尔框架 mirs.cn

实战应用:用在哪里

协议 schema 定了,前后端的编解码、兼容策略、错误处理就全定了。本文聚焦三个最常纠结的 Protobuf 设计点:字段存在性(optional 语义)、多态消息(oneof)、嵌套层数,给出 996 项目场景下的取舍依据。proto2 与 proto3 的行为差异是纠结的根源,先定版本:新项目直接 proto3,历史项目沿用 proto2 不迁移。

optional:存在与缺省是两回事

proto3 里标量字段没有"未设置"概念——0 和"没填"解码出来都是 0。活动奖励条数 0 条与"字段缺失"在业务上不同时,要显式建模:

protobuf
message QuestState {
  int32 quest_id = 1;
  int32 progress = 2;          // 0 与缺失同义,可接受
  optional bool claimed = 3;   // proto3 optional:区分"未领取(false)"与"未设置"
}

proto3 的 optional(3.15+ 版本编译器支持)生成存在性检查接口,has_claimed() 可用。判断标准:字段缺失会引发业务分支的,用 optional;纯数值展示类的,接受缺省值语义。

oneof:协议多态的标准解

一个消息体内"可能是 A 结果也可能是 B 结果",用 oneof 替代多个可空字段:

protobuf
message BattleResult {
  oneof result {
    WinInfo win = 1;
    LoseInfo lose = 2;
  }
  int32 duration = 3;          // 公共字段放 oneof 外
}

oneof 保证同一条消息里结果字段只有一个被设置,解码端用 which_result() 分支,消灭了"win 和 lose 同时有值"这类脏数据。字段总数在 oneof 内共享编号空间,新增结果类型只追加编号。

嵌套层数与包体

嵌套层级影响解码开销与代码可读性,实测 3 层与 6 层嵌套的同量数据,解码耗时相差约 15%,编解码错误率随层级上升。约定上限 4 层,超出的公共结构上提为平级引用。三个配套纪律:字段编号分配后写进 schema 注释(谁申请的、干什么用);每条 message 头注释写触发场景;schema 文件只加不改不删,废弃字段注释保留编号防复用。协议 schema 是前后端共用的地基,这些纪律执行半年,联调返工次数会下降一个量级。

← 返回文章地图返回研学路径