Skip to main content

Protobuf specification

This documentation mainly revise the Proto specification conventions and specific agreements between multiple languages to help everyone write more standard interfaces.

The API interface is unified based on HTTP/GRPC, and the protocol is defined through Protobuf, including complete Request/Reply, and corresponding interface error codes (Errors).

Directory structure

The API interface could be defined in api directory of the project, or could be managed in a unified repository, similar to googleapis, envoy-api.

For the proto in project, the api should be used as the root of package name.

go-micro-demo:
├── api // service API definition
│ ├── proto
│ │ ├── common
│ │ │ └── conf
│ │ └── demo-service
│ │ └── v1
│ │ └── demo.proto
│ ├── third_party // third party reference

For the proto in unified repository, the repository name should be use as the root of package name.

go-micro-apis:
├── api // service API definition
│ ├── proto
│ │ ├── common
│ │ │ └── conf
│ │ └── demo-service
│ │ └── v1
│ │ └── demo.proto
│ ├── third_party // third party reference

Package

The package name is used to generate gRPC request paths, or reference messages between Protos.

  • my.package.v1 is the API's directory, which defines the API of the services.

For example:

// Request URL: /<package_name>.<version>.<service_name>/{method}
package <package_name>.<version>;

go_package

option go_package = "github.com/devexps/go-micro/<package_name>;<version>";

java_package

option java_multiple_files = true;
option java_package = "com.github.gomicro.<package_name>.<version>";

Version

The version number marks the incompatible version and always used with <package_name>. When the API needs to be refactored, the incompatible structure should be updated.

Import

  • The proto dependencies' import path should be started from the root path.
  • third_party folder, always includes the proto from third-party such as protobuf, google rpc, google apis, etc.

Naming Convention

Directory Structure

The package name should be lower-case, and consist with the project directory structure. For example:

// project directory structure: my/package/v1/
package my.package.v1;

File Structure

The name of proto files should be lower_snack_case.proto. The contents of proto file should be ordered in the following below:

  1. Licence header (if applicable)
  2. File overview
  3. Syntax
  4. Package
  5. Imports (sorted)
  6. File options
  7. Everything else

Message and Field Naming

Use CamelCase (with an initial capital) for message names, for example: LoginRequest

User underscore_seperated_names for field names, including oneof field and extension names, for example: user_name

message LoginRequest {
required string user_name = 1;
}

Repeated Fields

Use pluralized names for repeated fields

message LoginReply {
repeated string keys = 1;
//...
repeated Account accounts = 20;
}

Enums

Use CamelCae for enum type names and CAPITALS_WITH_UNDERSCORES for value names:

enum FooBar {
FOO_BAR_UNSPECIFIED = 0;
FOO_BAR_FIRST_VALUE = 1;
FOO_BAR_SECOND_VALUE = 2;
}

Each enum value should end with a semicolon, not a comma. Prefer prefixing enum values rather than surrounding them with a wrapping message. The zero value enum should have the suffix UNSPECIFIED.

Services

If your .proto defines a RPC service, you should use CamelCase for both the service name and all RPC method names.

service FooService {
rpc GetFoo(GetFooRequest) returns (GetFooReply);
rpc ListFoo(ListFooRequest) returns (ListFooReply);
}

Comment

  • Service describes the information of this service.
  • Method describes the information of this API.
  • Field describes the information of this field.

Example

Service API Definition (demo.proto)

syntax = "proto3";

package gomicro.demo.v1;

// import block
// ...

option go_package = "github.com/devexps/go-micro/demo/v1;v1";
option java_multiple_files = true;
option java_package = "com.github.devexps.gomicro.demo.v1";

// Definition of the service
service Greeter {
// definition the function of API
rpc SayHello (HelloRequest) returns (HelloReply);
}

// the request of Hello
message HelloRequest {
// user's name
string name = 1;
}

// the response of Hello
message HelloReply {
// result data
string message = 1;
}

References