Protcol Buffers とは
プロトコルバッファー (Protocol Buffers、または protobuf) は、Google が開発した、構造化したデータをシリアライズするためのフォーマットです。 同じく Google が開発した gRPC 通信プラットフォームで採用されており、XML や JSON などのテキストベースの API より効率的な通信を行うことができるという特徴を持っています。
- データをコンパクトに表現できるため、通信やパース処理が高速
- 強い型付けを行うことでき、サーバー、クライアントの安全なコーディングが可能
- 定義変更時の互換性を考慮したフォーマット
- OS やプログラミング言語などに非依存
データ構造やサービス形式の定義は、.proto
拡張子を持つ プロトコル定義ファイル (Proto Definition file) で行います。
この .proto
ファイルを protoc
コマンド(プロトコルバッファーコンパイラ)でコンパイルすると、各言語用のソースコードを生成することができます。
protoc
コマンドは各種プログラミング言語用のコードを生成するわけですが、そのためには、protoc コマンド本体 と 各言語用のプラグイン(protoc-gen-go
など)がインストールされている必要があります。
C++ や C#、Kotlin、Python、Ruby などのコード生成は組み込みで対応していますが、Go 言語用のプラグインなどは別途インストールする必要があります。
protoc 本体のインストール
protoc
コマンド (Protocol Buffers Compiler) は、Linux(Ubuntu 系)や macOS ではパッケージマネージャーを使ってインストールしてしまうのが簡単です。
インストールするパッケージの名前は protobuf
や protobuf-compiler
であることに注意してください。
macOS (Homebrew) の場合
$ brew install protobuf # インストール
$ brew upgrade protobuf # バージョン更新
Linux (apt) の場合
$ apt install -y protobuf-compiler
プリビルド版を使う場合
あるいは、各 OS 用のバイナリを GitHub のリリースページ からダウンロードし、protoc
コマンドにパスを通します。
例えば、Windows であれば protoc-3.20.0-win64.zip
などをダウンロードします。
次のように protoc
コマンドを実行できるようになれば OK です。
$ protoc --version
libprotoc 3.20.0
.proto ファイルをコンパイルしてみる
次のような簡単な .proto
ファイルを入力ファイルとして用意します。
syntax = "proto3";
message Person {
optional string name = 1;
optional int32 id = 2;
optional string email = 3;
}
C# のコードを生成
例えば、次のように実行すると、C# 用のソースコードを生成することができます。
--csharp_out=<OUT_DIR>
というオプションで、C# ソースコードの出力先ディレクトリを指定しています。
$ mkdir gen
$ protoc --csharp_out=gen proto/person.proto
$ ls gen
Person.cs
Python のコードを生成
Python 用のソースコードを生成したければ、同様に次のようにします。
出力ディレクトリは --python_out=<OUT_DIR>
オプションで指定します。
$ protoc --python_out=gen proto/person.proto
その他の言語のコードを生成
他にも各言語用のソースコードを生成するオプションが用意されており、次のようにヘルプ表示すると標準でサポートしている言語を確認できます。
$ protoc --help | grep OUT_DIR
--cpp_out=OUT_DIR Generate C++ header and source.
--csharp_out=OUT_DIR Generate C# source file.
--java_out=OUT_DIR Generate Java source file.
--js_out=OUT_DIR Generate JavaScript source.
--kotlin_out=OUT_DIR Generate Kotlin file.
--objc_out=OUT_DIR Generate Objective-C header and source.
--php_out=OUT_DIR Generate PHP source file.
--python_out=OUT_DIR Generate Python source file.
--ruby_out=OUT_DIR Generate Ruby source file.
言語拡張 (protoc-gen-xxx)
protoc
が標準でサポートしてない言語のコードを生成するには、追加のプラグイン(実際はただのコマンド)をインストールする必要があります。
追加でインストールするコマンドは protoc-gen-<言語名>
という名前であり、そのコマンドがシステムに存在していると、protoc
コマンドの --<言語名>_out
というオプションが有効になります。
例: Go 言語用プラグイン (protoc-gen-go)
例えば、Go 言語用のプラグインである protoc-gen-go
をインストールすると、--go_out
オプションが使えるようになります。
# バージョン指定でインストールする場合(推奨)
$ go install google.golang.org/protobuf/cmd/protoc-gen-go@v1.28.0
# 最新版をインストールする場合
$ go install google.golang.org/protobuf/cmd/protoc-gen-go@latest
# 確認
$ protoc-gen-go --version
protoc-gen-go v1.28.0
Go 言語用のコードを出力する場合は、.proto
ファイル内の option go_package
でパッケージ名を設定しておく必要があります。
syntax = "proto3";
option go_package = "example.com/myapp";
message Person {
optional string name = 1;
optional int32 id = 2;
optional string email = 3;
}
次のようにすると、gen
ディレクトリ以下に Go コードが生成されます。
$ protoc --go_out=gen proto/person.proto
.proto
ファイルで指定したパッケージ名に従ってディレクトリ階層ができます。
gen/example.com/myapp/person.pb.go
.proto
ファイル内でパッケージ名を指定するのではなく、protoc
コマンドの --go_opt=M...
オプションで次のように指定することもできます。
$ protoc --go_out=gen \
--go_opt=Mproto/person.proto=example.com/myapp \
proto/person.proto
=
が 2 回出てくるのでちょっと分かりにくいですが、proto/person.proto
ファイルのパッケージ名を example.com/myapp
に設定しています。