速習 .proto ファイルの書き方


はじめに

.proto ファイルの記述をサクっと始めるための記事。
基礎的な内容のみに絞り記述する。

公式ドキュメントは Language Guide (proto3) である。

.proto ファイルの書き方

構文

ファイルの全体像を先に示す。

syntax = "proto3";

package myapp;

service AddressBookService {
  rpc Search (SearchRequest) returns (SearchResponse);
}

message SearchRequest {
  string name = 1;
}

message SearchResponse {
  Person person = 1;
}

message Person {
  int32 id = 1;
  string name = 2;
  string email = 3;
}

バージョン

バージョンを指定する。

syntax = "proto3;

パッケージ

パッケージを指定する。
名前の衝突を避けるための名前空間の役割を果たす。

pakcage myapp;

import

import 文で他のパッケージを読み込むことができる。
対象には パッケージ名.オブジェクト でアクセスすることができる。

import "../other_app/addressbook.proto";

message OtherApp {
	other_app.Person = 1;
}

サービスとメソッド

サービスとはメソッドを論理的にまとめたものである。
メソッドは1つのエンドポイントとなる。

service AddressBookService {
  rpc Search (SearchRequest) returns (SearchResponse);
}

スカラー型

型には主にスカラー型とメッセージ型の2つがある。
その他にはリスト、マップ、Enum などがある。

本記事ではではよく使いそうなスカラー型を抜粋する。
全てのスカラー型は Scalar Value Types に書いてある。

整数

int32
int64

float
double

文字列

string

真偽値

bool

バイト文字列

bytes

メッセージ型

メッセージ型と呼ばれる複数のフィールドを持つ型を定義できる。
コードを自動生成する際に、構造体やクラスとして書き出される。

message Person {
	int32 id = 1;
	string name = 2;
	repeated string items = 4;

    string phone_number = 5 [deprecated = true]

	reserved 3, 6 to 10;
	reserved "fax_number";
}

タグナンバー

なぜ 1 や 2 を代入しているのかと感じるが、これはタグナンバーと呼ばれるものである。
コードのシリアライズ後のフォーマットでフィールドを識別するために使用される。

メッセージ内で一意である必要がある。

廃盤

運用中にフィールドを削除した場合、そのタグナンバーは廃盤とすることが望ましい。
再利用すると、フィールド識別上の不具合につながる可能性があるためである。

reserved

廃盤であることを明示する識別子。

deprecated

非奨励であることを明示するオプション。

列挙型

0始まりで記述する。

enum PhoneType {
	option allow_alias = true;

	UNKOWN = 0;
	MOBILE = 1;
	OFFICE = 2;
	SCHOOL = 2;
}

allow_alias

同じ値に異なるラベルを割り当てることを許可するオプション。
ラベルを2つ以上指定した場合、エイリアスとして動作する。

リスト

いわゆる配列である。

repeated string items = 1;

repeated

リスト(配列)を表現する識別子。
スカラー型、メッセージ型のどちらにも適用可能。

マップ

いわゆる連想配列である。

map<string, AddressBook> address_books = 1;

キー

キーには整数値、文字列、真偽値のみ指定可能。

Well Known Types

Build-in で事前定義された便利なメッセージ型郡。
日時、期間、Any などが揃っている。
google.prorotbuf パッケージで定義されている。

import "google/protobuf/timestamp.proto";
import "google/protobuf/duration.proto";

終わりに

gRPC の記事も書いたのでよかったらぜひ。