Go 语言的 Protobuf 模块发布了一个新的 API,旨在改进现有 API 的性能和灵活性。
**背景:现有的开放结构体 API**
现有的 API 被称为开放结构体 API,因为它允许程序直接访问生成的结构体类型。该 API 使用指针来表示字段的存在状态,例如,可以使用 `proto.String` 设置 BackendServer 字段并存储值。
**新的不透明 API**
新的不透明 API 旨在解耦生成的代码 API 与底层内存表示。它隐藏了结构体的字段,并通过访问器方法(如 `GetBackendServer`、`SetBackendServer`)来访问和修改字段。
**不透明结构体占用更少的内存**
不透明 API 使用位字段来表示字段的存在状态,而不是指针,从而减少了内存占用。
**性能改进**
减少内存分配也提高了 protobuf 消息的解码效率。在包含更多基本字段的消息中,不透明 API 的解码速度更快,分配次数更少。
**动机:延迟解码**
延迟解码是一种性能优化,它只在首次访问子消息时才对其内容进行解码。不透明 API 支持延迟解码,因为它将字段设为私有,并通过访问器方法访问。
**动机:减少指针比较错误**
不透明 API 避免了由于直接比较指针而导致的错误,因为所有访问都必须通过访问器方法进行。
**动机:减少意外共享错误**
不透明 API 避免了由于意外复制指针而导致的错误,因为访问器方法接收的是值而不是指针。
**动机:修复反射方面的尖锐边缘**
通过隐藏结构体的字段,不透明 API 鼓励开发者使用 protobuf 反射而不是 Go 反射。
**动机:实现理想的内存布局**
不透明 API 使得将来对特定工作负载进行内存布局优化成为可能。
**迁移**
可以根据自己的时间安排进行迁移,或者完全不迁移。建议在新开发中选择不透明 API。
**混合 API**
混合 API 同时保留了开放结构体 API 和不透明 API 的特性。
**重写代码到不透明 API**
提供迁移指南,指导开发者如何将代码迁移到不透明 API。
**发布的生成代码的建议:使用混合 API**
建议发布生成代码(.pb.go 文件)的包切换到混合 API,发布 .pb.go 和 _protoopaque.pb.go 两个文件,让使用者可以自行选择迁移时间。
**启用延迟解码**
迁移到不透明 API 后,可以通过在 .proto 文件中使用 `[lazy = true]` 注解来启用延迟解码。