まくろぐ
更新: / 作成:

.proto ファイルでメッセージやサービスを定義するときのコーディング規約をまとめておきます。 Google が Style Guide として指針をまとめていますが、プロジェクト内に既に .proto ファイルがある場合は、一貫性を保つように記述するのがよいとされています。

.proto ファイルの例
syntax = "proto3";

package endpoints.examples.bookstore;

option java_multiple_files = true;
option java_outer_classname = "BookstoreProto";
option java_package = "com.google.endpoints.examples.bookstore";

import "google/protobuf/empty.proto";

service Bookstore {
  rpc ListShelves(google.protobuf.Empty) returns (ListShelvesResponse) {}
  rpc CreateShelf(CreateShelfRequest) returns (Shelf) {}
  rpc GetShelf(GetShelfRequest) returns (Shelf) {}
  rpc DeleteShelf(DeleteShelfRequest) returns (google.protobuf.Empty) {}
  rpc ListBooks(ListBooksRequest) returns (ListBooksResponse) {}
  rpc CreateBook(CreateBookRequest) returns (Book) {}
  rpc GetBook(GetBookRequest) returns (Book) {}
  rpc DeleteBook(DeleteBookRequest) returns (google.protobuf.Empty) {}
}

message Shelf {
  int64 id = 1;
  string theme = 2;
}

message Book {
  int64 id = 1;
  string author = 2;
  string title = 3;
}

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

全般

  • .proto ファイル名はすべて小文字 + アンダースコア(例: lower_snake_case.proto
  • .proto ファイルは、proto という独立したディレクトリに入れて、別のソースコードとは分けて管理する(参考: File location
    • 言語に依存したディレクトリ階層に配置することは推奨されていません。例えば、Java のパッケージ階層に合わせて .proto ファイルを配置すると、Java ではわかりやすいと感じるかもしれませんが、他の言語で使おうとしたときにその階層構造が意味を持たないことがあります。
  • 1 行は 80 文字 まで
  • インデントはスペース 2 文字
  • 文字列リテラルは ダブルクォート で囲む(例: "Hoge"

.proto の構成

.proto ファイルの内容は次のような順番で記述します。

  1. ライセンス / コピーライト(必要があれば)
  2. 概要 / Overview
  3. 構文バージョン (syntax)
    • 例: syntax = "proto3";
    • これを省略すると、デフォルトで "proto2" とみなされてしまいます。
  4. パッケージ定義 (package)
    • 例: package example.echo;
    • package の指定はオプションです。例えば、Ruby や C# ではデフォルトでネームスペースに反映されますが、Python では無視されます(Python はディレクトリ構造でモジュール管理するため)。
  5. インポート (import)
    • 例: import "message/other.proto";
    • import ディレクティブはアルファベト順にソートしておきます。
  6. オプション (option)
    • 例: option go_package = "github.com/maku77/hello";
    • 例: option java_package = "com.example.hello";
  7. その他(残り全部)

パッケージ

package example.echo;
  • パッケージ名はすべて小文字 (lowercase)
  • できるだけ .proto ファイルのディレクトリ階層と対応させる(つまり、proto ディレクトリ以下のディレクトリ名)

メッセージ

message SongServerRequest {
  optional string song_name = 1;
}
  • メッセージ名は CamelCase で、フィールド名は lower_snace_case の形
    • .proto ファイル内で song_name というフィールド名で定義しても、Java や Kotlin のコードを生成したときは、正しく getSongName() のような名前になるので心配しなくて大丈夫です。
  • フィールド名のサフィックスに数値を付ける場合は、アンダースコアを挟まない
    string song_name1;   // ✅ Good
    string song_name_1;  // ❌ NG
    
  • repeated 修飾子のついたフィールドの名前は複数形にする
    repeated string keys = 1;  // ✅ Good
    repeated string key = 1;   // ❌ NG
    

Enum

  • Enum 名は CamelCase で、各値は CAPITALS_WITH_UNDERSCORES の形にする
  • 各値の行末はセミコロン (;) で終わる
  • 0 の値を持つものは、_UNSPECIFIED サフィックスを付ける
    enum FooBar {
      FOO_BAR_UNSPECIFIED = 0;
      FOO_BAR_FIRST_VALUE = 1;
      FOO_BAR_SECOND_VALUE = 2;
    }
    
  • 各値のプレフィックスとして Enum 名に対応する名前を付ける(上記の例では FOO_BAR_

サービス

  • サービス名は CamelCase で、RPC メソッド名も CamelCase の形にする
    service FooService {
      rpc GetSomething(GetSomethingRequest) returns (GetSomethingResponse);
      rpc ListSomething(ListSomethingRequest) returns (ListSomethingResponse);
    }
    

その他

  • requiredproto3 以降は使わない
  • groupsproto3 以降は使わない

関連記事

まくろぐ
サイトマップまくへのメッセージ