Chapter 03

protoファイルでProcedureを定義する

さき(H.Saki)
さき(H.Saki)
2022.06.23に更新

この章について

RPCは関数の呼び出しのわけですから、その関数の定義・戻り値・引数の定義をしていく必要があります。
そのProcedureの定義を、gPRCではprotoファイルというものを使って行っています。

この章では、protoファイルの記述の仕方について簡単に触れていきます。

protoファイルの記述方式

簡単なprotoファイルの例を以下に示します。

// protoのバージョンの宣言
syntax = "proto3";

// protoファイルから自動生成させるGoのコードの置き先
// (詳細は4章にて)
option go_package = "pkg/grpc";

// packageの宣言
package myapp;

// サービスの定義
service GreetingService {
	// サービスが持つメソッドの定義
	rpc Hello (HelloRequest) returns (HelloResponse); 
}

// 型の定義
message HelloRequest {
	string name = 1;
}

message HelloResponse {
	string message = 1;
}

Protocol Buffer Languageのバージョン指定

protoファイルを記述するProtocol Buffer Languageには、現在proto2proto3の2種類のバージョンが存在します。
最新バージョンであるproto3を使うには、明示的にバージョン指定をする必要があります。これを省略するとptoro2で書かれた記述とみなされます。

// protoのバージョンの宣言
syntax = "proto3";

packageの宣言

詳細は後述しますが、protoファイルでは「他のprotoファイルで定義された型を使って記述する」ということもできるようになっており、その際に「パッケージ名.型名」という形で他のprotoファイル内の型を参照することになります。
意味合いとしてはGoでのパッケージ宣言と同じです。

// packageの宣言
package myapp;

サービスとメソッドの定義

gRPCのPの部分であるProcedureの定義をしていきます。
一般的には、gRPCで呼び出そうとするProcedure(関数)をメソッド、そしてそのメソッドをいくつかまとめて一括りにしたものをサービスと呼びます。

// サービスの定義
service GreetingService {
	// サービスが持つメソッドの定義
	rpc Hello (HelloRequest) returns (HelloResponse); 
}

この例ですと以下2つを行なっています。

  • 引数にHelloRequest型、戻り値にHelloResponse型を持つメソッドHelloを定義
  • Helloメソッド一つを持つGreetingServiceサービスを定義

メッセージ型の定義

メソッドを定義したところで、今度は引数・戻り値に使われていたHelloRequest型・HelloResponse型を定義します。

// 型の定義
message HelloRequest {
	string name = 1;
}

message HelloResponse {
	string message = 1;
}

HelloRequest型にはstring型のnameフィールドを、HelloResponse型にはstring型のmessageフィールドを持たせました。

protoファイル内で定義できる型

上で紹介したHelloRequest型・HelloResponse型にはstring型しか使用していませんが、他にもint型やbool型、enum型といった様々な型がprotobufには用意されています。
どんな型・どんなデータ構造が用意されているのかについては、詳細に書いていくとそれだけで本一冊が書けてしまう内容なのでここでは割愛させていただきます。

勉強するにあたって参考になりそうな文献を2つ紹介します。

Well Known Types

Protocol Buffersに組み込みで用意されている型以外にも、Googleが定義してパッケージとして公開した便利型の集合「Well Known Types」というものがあります。

https://developers.google.com/protocol-buffers/docs/reference/google.protobuf

時刻を表すTimestamp型や、引数・戻り値なしを表現するためのEmpty型のような、デフォルトでは用意されていないが使いたい場面が多い便利型がgoogle.protobufというパッケージ名で多数定義されています。

// Timestamp型を使ってMyMessage型を定義した例

// Timestamp型を記述しているprotoファイルをimport
import "google/protobuf/timestamp.proto";

message MyMessage {
	string message = 1;
	// パッケージ名"google.protobuf" + 型名"Timestamp"で記述
	google.protobuf.Timestamp create_time = 2;
}