编号 | 191 |
---|---|
原文链接 | https://google.aip.dev/191 |
状态 | 批准 |
创建日期 | 2019-07-25 |
更新日期 | 2019-07-25 |
统一的文件和目录结构,虽然在技术上差别不大,但可以让用户和审查者更容易阅读API界面定义。
指南
注意 以下指南适合于使用protobuf定义的API,例如Google内部使用的API。本指南的主要思想同样适合于使用其他规范性语言或格式定义的API,但有些具体建议可能无效。
语法
使用protocol buffer定义API时 必须 使用 proto3
语法。
同一个包
使用protocol buffer定义的API, 必须 在同一个包中定义独立的API,包名 必须 以版本号结尾。例如:
syntax = "proto3";
package google.cloud.translation.v3;
Google API 必须 位于和protocol buffer package
指令一致的目录中。例如,上述包对应的目录为 google/cloud/translation/v3
。
文件名
将API定义分拆成多个文件通常很有用。文件名 必须 使用 snake_case
。
API 应当 有一个显著的“入口”文件,通常以API本身命名。具有少量接口的API(例如Google Cloud Pub/Sub的 Publisher
和 Subscriber
) 可以 为每个服务设置独立的入口文件。
只有一个文件的API 应当 使用与API名字一致的文件名。
API service
和远程过程调用请求及应答 message
应当 在同一文件中定义。
请记住,文件名通常会成为客户端库中的模块名,客户会在 import
或 use
语句中使用它们。因此,选择一个描述性强,并且不包含语言关键字的文件名非常重要。例如名为 import.proto
的文件在Python中可能会遇到问题。
注意 版本 不得 用作文件名,这会在客户端库中产生奇怪的导入语句。禁止使用诸如
v3.proto
或v1beta1.proto
的文件名。
文件布局
在文件中,高级别和重要定义 应当 放在低级别和次要定义之前。
在proto文件中,组件 应当 按以下顺序排列。每个部分之间 应当 用空行分隔:
- 版权和许可证声明(如果需要)。
- proto
syntax
语句。 - proto
package
语句。 - 任何
import
语句,按字母序排列。 - 文件级别的
option
语句。 - 服务
service
定义。- 方法 应当 按照所使用的资源分组,标准方法 应当 放在自定义方法之前。
- 资源
message
定义。上级资源 必须 在下级资源之前定义。 - 远程过程调用请求和应答
message
定义,按相应方法的顺序排列。每个请求消息 必须 在其对应的应答消息(如果有)之前。 - 其他
message
定义。 - 顶级
enum
定义。
包选项
protocol buffer可以包含选项,声明生成代码的包或名字空间(取决于目标编程语言)。例如,声明 go_package
或 csharp_namespace
将会覆盖自动推断的包名。
定义API时,遵守以下规则:
- Java
- 必须 设置
java_package
。正确的值通常是带有顶级域名前缀的proto包名。例如com.google.example.v1
。 - 必须 将
java_multiple_files
设置为true
。 - 必须 设置
java_outer_classname
, 应当 将其设置为proto文件名,使用PascalCase
并添加后缀Proto
。例如LibraryProto
。
- 必须 设置
- 其他语言
- 对于其他语言的包或名字空间指令, 必须 要么在proto包的每个文件中都设置,要么全都不设置。如果设置了,每个文件中的值 必须 相同。
- 如果proto包的某部分是复合名字(例如accessapproval), 必须 指定C#、Ruby和PHP选项,以处理
PascalCase
分词位置。例如:option csharp_namespace = "Google.Cloud.AccessApproval.V1"; option php_namespace = "Google\\Cloud\\AccessApproval\\V1"; option ruby_package = "Google::Cloud::AccessApproval::V1";
go_package
值直接取决于Go代码的管理方式,即模块名字是基于VCS还是使用远程导入路径。但二者通常具有相同结构。- 模块 可能 因产品领域而异,例如
google.cloud.accessapproval.v1
出现在模块cloud.google.com/go/accessapproval
中。 - 包导入路径 应当 从proto包派生。
- proto包名中的API版本 应当 以
api
为前缀,例如proto包名中的v1
变为apiv1
。 - 导入路径末端 应当 基于proto包名中的产品名字,并且 必须 以
pb
为后缀,例如accessapproval
变为accessapprovalpb
。 - 具体值 应当 由管理生成代码的团队决定。
- 模块 可能 因产品领域而异,例如
所有包选项 应当 按名字的字母序排列。关于语言包选项的更多信息,请参考Protocol Buffer文档。
重要 虽然Java之外的其他语言对于没有复合名字的API有合理的默认值,但请注意, 添加 选项(值不等于默认值)将对该语言客户端产生破坏性更改。在发布proto时,请确认省略选项是有意为之的。
理由
Java包选项
将选项 java_multiple_files
设置为 true
可以获得更清晰的文件结构。它让 protoc
为每个Protocol Buffer类型创建独立的输出文件,从而允许更细粒度的导入。选项 java_outer_classname
必须配合 java_multiple_files
选项使用。它让 protoc
将每个Protocol Buffer类型包装在Java类中,类名字是选项值。这可以防止生成的类之间存在名字冲突。
Go包选项
Go包选项由管理生成代码的团队决定,因为它与团队的源代码管理实践有直接关系。允许每个proto包自行决定其Go包,将导致代码管理出现不一致和摩擦。在Go客户端团队内部,保持统一的Go包名字结构对于统一的用户体验至关重要。
修订记录
- 2024-06-13 添加Go包选项指南。
- 2024-06-05 添加Java包选项理由。
- 2023-02-24 添加关于protocol buffer语法的指南。
- 2022-10-18 添加关于Ruby/PHP/C#选项的指南。
- 2019-11-18 添加关于包选项的指南。