grpc idl 简单介绍

在 gRPC 中,IDL(接口定义语言)是通过 Protocol Buffers(.proto 文件) 来定义的。为了保证你的 gRPC 接口具有清晰、可维护、可扩展、跨语言兼容等特性,编写 .proto 文件时应遵循一系列编码规范和最佳实践。

下面是 gRPC/Protobuf .proto 文件的编码指导,包括命名规范、结构组织、字段使用建议、版本控制等:


1. 文件结构组织规范

文件命名

  • 使用 小写 + 下划线 命名:如 user_service.proto。
  • 文件名应能体现模块或服务名称。

包结构:

syntax = "proto3";

package myapp.user;  // 多层命名空间,避免冲突

option go_package = "github.com/yourorg/yourproject/gen/userpb";  // Go 等语言需要指定导入路径

推荐:一个文件只定义一个 service,如果 service 很复杂,可拆分多个 proto 文件。


2. 消息定义规范

命名风格

  • 消息/服务/枚举使用 PascalCase:如 UserRequest、UserResponse、UserService。
  • 字段使用 snake_case:如 user_id、email_address。

字段编号:

  • 使用 1 ~ 15 编号范围保留给高频使用字段(性能更高)。
  • 不要修改已发布字段的编号。

示例:

message UserRequest {
  int64 user_id = 1;
  string email = 2;
}

3. 服务与 RPC 设计规范

命名规范

  • Service 命名应体现业务领域,如 UserService、AuthService。
  • 方法名使用 PascalCase,如 GetUser、CreateUser。

请求和响应推荐

  • 请求消息以 XxxRequest 结尾,响应以 XxxResponse 结尾。

示例

service UserService {
  rpc GetUser (UserRequest) returns (UserResponse);
  rpc CreateUser (CreateUserRequest) returns (CreateUserResponse);
}

4. 枚举与默认值

  • 枚举的第一个值必须为 0,通常命名为 ENUM_UNSPECIFIED 或 UNKNOWN。
  • 避免使用 magic numbers。
enum UserStatus {
  USER_STATUS_UNSPECIFIED = 0;
  USER_ACTIVE = 1;
  USER_INACTIVE = 2;
}

5. 可扩展性设计建议

  • 不要删除字段编号,即使字段废弃了,也应保留编号(可加注释标记 deprecated)。
  • 留空编号以备将来使用。
  • 使用 reserved 关键字保留字段名或编号,防止冲突:
message User {
  reserved 3, 4;          // 保留编号
  reserved "old_field";   // 保留字段名
}

6. 错误处理推荐(跨语言)

gRPC 使用 Status 返回错误,建议定义自定义错误码:

import "google/rpc/status.proto";
import "google/rpc/code.proto";

service AuthService {
  rpc Login(LoginRequest) returns (LoginResponse) {
    option (google.api.http) = {
      post: "/v1/login"
      body: "*"
    };
  }
}

建议返回 google.rpc.Status 作为 error detail,方便统一错误处理。


7. 注释和文档生成

  • 使用 // 或 / ... */ 注释消息、字段、方法,支持 protoc-gen-doc 等工具自动生成文档。
  • 注释写清楚单位、约束、默认值、特殊说明。
// 用户注册请求
message RegisterRequest {
  // 用户邮箱地址(必须为合法格式)
  string email = 1;
}

8. gRPC REST 网关支持(可选)

如你使用 gRPC Gateway(用于提供 REST 接口),应加上 google.api.http 的 option:

import "google/api/annotations.proto";

service UserService {
  rpc GetUser (GetUserRequest) returns (User) {
    option (google.api.http) = {
      get: "/v1/users/{user_id}"
    };
  }
}

9. 通用封装结构推荐(可选)

定义通用结构,便于扩展或统一返回格式:

message BaseResponse {
  int32 code = 1;
  string message = 2;
}

message PageRequest {
  int32 page = 1;
  int32 size = 2;
}

message PageResponse {
  int32 total = 1;
}

10. 目录结构推荐(大型项目)

proto/
├── user/
│   ├── user.proto
│   └── user_service.proto
├── common/
│   ├── error.proto
│   ├── pagination.proto

总结:Checklist(编码规范)

类别规范建议
命名PascalCase(类型),snake_case(字段)
字段编号不重用,保留废弃编号
扩展性使用 reserved,保留字段空间
服务设计明确语义,方法命名动词开头
注释字段、消息、方法写清楚注释
错误处理建议接入 google.rpc.Status
REST 支持使用 google.api.http 注解
通用结构可封装统一响应、分页等结构
Logo

北京人形旗下天工造物具身智能开源社区,聚焦具身天工与慧思开物两大平台

更多推荐