ページの作成
親となるページを選択してください。
親ページに紐づくページを子ページといいます。
例: 親=スポーツ, 子1=サッカー, 子2=野球
子ページを親ページとして更に子ページを作成することも可能です。
例: 親=サッカー, 子=サッカーのルール
親ページはいつでも変更することが可能なのでとりあえず作ってみましょう!
このチュートリアルでは、Go言語とgRPCを使い、「名前を送ると挨拶を返す」ごく小さなサービス(Greeter)をゼロから組み立てます。具体的には、.protoファイルでサービスを定義し、protocでGoコードを生成し、サーバとクライアントを実装して、実際に通信させるまでを、コマンドとコードを示しながら一歩ずつ解説します。gRPCの公式クイックスタートをなぞりつつ、各ステップで「何をしているのか」を補足する構成です。
| この記事の要点 |
|---|
|
全体の流れ
gRPC アプリケーションの開発は、おおまかに次の順序で進みます。最初に全体像をつかんでおくと、各ステップの位置づけが分かりやすくなります。
| 手順 | やること |
|---|---|
| 1. 準備 | Go・protoc・コード生成プラグインをインストールし、PATH を通す |
| 2. 定義 | .proto ファイルにサービスとメッセージを記述する |
| 3. 生成 | protoc で .proto から Go のコード(型・クライアント・サーバ雛形)を生成する |
| 4. サーバ実装 | 生成されたインターフェースを満たすように、サーバ側のロジックを書く |
| 5. クライアント実装 | 生成されたクライアントを使ってサーバを呼び出すコードを書く |
| 6. 実行 | サーバを起動し、別のターミナルからクライアントを実行して通信を確認する |
1. 準備:必要なツールのインストール
まず、開発に必要な3種類のツールをそろえます。
- Go … 本体。比較的新しいバージョンを推奨します。
- Protocol Buffers コンパイラ(protoc) … .proto ファイルからコードを生成するコンパイラ。
- Go 用のコード生成プラグイン … protoc に Go コードを出力させるためのプラグイン2種。
protoc 本体は、OS のパッケージマネージャや配布アーカイブから導入します(導入方法は OS により異なるため、公式の案内を参照してください)。続いて、Go 用のプラグインを go install で導入します。
$ go install google.golang.org/protobuf/cmd/protoc-gen-go@latest |
ここで導入する2つのプラグインの役割は次のとおりです。
- protoc-gen-go … メッセージ型(リクエスト/レスポンスの構造体)を生成する。
- protoc-gen-go-grpc … サービスのクライアント・サーバ用インターフェースを生成する。
なお @latest は最新版を取得する指定です。再現性を重視する場合は、特定のバージョンタグ(例:@v1.34.0 のような形式)を指定する運用も考えられます。バージョンの対応関係は更新されるため、固定する場合は公式の案内で確認してください。
# protoc 本体が呼べることの確認(例) |
※ protoc コマンド、および go install で入れたプラグイン(通常は $GOPATH/bin もしくは $HOME/go/bin に置かれます)を、ターミナル/コマンドプロンプトから実行できるよう PATH を通してください。PATH が通っていないと、後段のコード生成でプラグインが見つからずエラーになります(具体的な設定方法は OS ごとに異なるため省略します)。
2. 定義:.proto ファイルを書く
gRPC のサービスは Protocol Buffers(protobuf)で定義します。今回は、クライアントから HelloRequest を受け取り、サーバから HelloReply を返す SayHello という RPC メソッドを持つ Greeter サービスを定義します。
例として、次のような helloworld.proto を考えます。
|
syntax = "proto3"; option go_package = "example.com/helloworld/helloworld"; package helloworld; // 挨拶サービスの定義 // 名前を含むリクエストメッセージ // 挨拶文を含むレスポンスメッセージ |
各要素のポイントは以下のとおりです。
- syntax = "proto3"; … protobuf の構文バージョン。現在は proto3 が一般的です。
- option go_package … 生成される Go コードのインポートパス(パッケージの位置)を指定します。プロジェクトのモジュールパスに合わせます。
- service / rpc … 呼び出せるメソッドを定義します。
rpc メソッド名 (引数型) returns (戻り値型)という形です。 - message … やり取りするデータ構造。各フィールドの末尾にある
= 1はフィールド番号で、エンコード時の識別子として使われます(値の代入ではありません)。一度割り当てた番号は変更しないのが原則です。
3. 生成:protoc で Go コードを作る
.proto を書いたら、protoc にプラグインを組み合わせて Go コードを生成します。.proto があるディレクトリで、次のようなコマンドを実行します(パスはプロジェクト構成に合わせて調整してください)。
$ protoc --go_out=. --go_opt=paths=source_relative \ |
このコマンドの各オプションの意味は次のとおりです。
| オプション | 役割 |
|---|---|
| --go_out | protoc-gen-go によるメッセージ型コードの出力先 |
| --go-grpc_out | protoc-gen-go-grpc によるサービス用コードの出力先 |
| paths=source_relative | .proto の位置を基準に、生成ファイルの出力場所を決める指定 |
成功すると、おおむね次の2ファイルが生成されます。
- helloworld.pb.go …
HelloRequest/HelloReplyなどのメッセージ型。 - helloworld_grpc.pb.go …
GreeterClient(クライアント)やGreeterServer(サーバ用インターフェース)など。
以降のサーバ・クライアント実装では、これらの生成済みコードを pb という別名でインポートして利用します。
4. サーバ実装
生成された GreeterServer インターフェースを満たすように、サーバ側のロジックを実装します。下記は greeter_server/main.go 相当の例です。まずは全体を眺めてから、要所を個別に解説します。
|
// コマンドライン引数を処理するための変数 // Greeter サービスを実装する構造体 // SayHello メソッドの実装 func main() { // 指定ポートでリッスン // gRPC サーバーを作成 // Greeter サービスを登録 log.Printf("server listening at %v", lis.Addr()) // サーバー起動(リクエスト待機) |
このコードは gRPC を使って Greeter サービスのサーバを実装しており、コマンドライン引数からポート番号を受け取って起動します(引数を省略すればデフォルトの 50051 が使われます)。サーバはクライアントからの挨拶リクエストを受け付け、挨拶メッセージを応答として返します。要点を順に見ていきます。
(1) UnimplementedGreeterServer の埋め込み
server 構造体に pb.UnimplementedGreeterServer を埋め込んでいます。これは生成コードが提供する型で、将来サービスにメソッドが追加されても既存のサーバがコンパイルエラーにならないようにするための仕組み(前方互換の土台)です。
(2) SayHello メソッドの実装
SayHello は、生成された GreeterServer インターフェースが要求するメソッドです。受け取った HelloRequest の名前をログ出力し、"Hello " を前置した HelloReply を返します。RPC のビジネスロジックは、このように生成インターフェースのメソッドとして書きます。
(3) リッスンの設定
lis, err := net.Listen("tcp", fmt.Sprintf(":%d", *port)) |
この行は、サーバが接続を待ち受けるネットワークアドレスを設定しています。動きを分解すると次のとおりです。
fmt.Sprintf(":%d", *port)… ポート番号を":50051"のような文字列に整形します。net.Listen("tcp", ...)… TCP を指定し、そのアドレスでクライアント接続を待ち受けるnet.Listenerを作成します。lis, err := ...… 生成されたnet.Listenerとエラーを受け取ります。ポートが使用中などで失敗するとここでerrに値が入ります。
(4) サーバの生成・登録・起動
grpc.NewServer() で gRPC サーバを作り、pb.RegisterGreeterServer で自作の server をそのサーバに紐付けます。最後に s.Serve(lis) でリクエストの受付を開始し、以降はクライアントからの呼び出しを待ち続けます。
5. クライアント実装
続いて、サーバを呼び出すクライアントを実装します。下記は greeter_client/main.go 相当の例です。
(1) コマンドライン引数の定義
var ( |
接続先アドレス addr と、挨拶する相手の名前 name をコマンドライン引数として定義しています。flag パッケージは Go 標準ライブラリで、コマンドライン引数を扱うためのものです。後述の flag.Parse() を呼ぶことで実際の引数値が反映されます。呼ばなければ、第2引数で指定したデフォルト値(ここでは localhost:50051 と defaultName)が使われます。
(2) サーバへの接続
conn, err := grpc.NewClient(*addr, grpc.WithTransportCredentials(insecure.NewCredentials())) |
gRPC サーバへの接続(チャネル)を用意します。ここでは学習目的のため、TLS を使わない insecure.NewCredentials() を指定しています。実運用では、平文通信ではなく TLS などの安全な認証情報を用いるのが一般的です。
なお、接続生成 API は gRPC のバージョンによって推奨される関数が変わってきています。比較的新しい版では grpc.NewClient が用いられます。古いコード例では grpc.Dial が使われていることがありますが、お使いのバージョンの公式ドキュメントに合わせて選んでください。
(3) クライアントの生成
c := pb.NewGreeterClient(conn) |
生成コードが提供する NewGreeterClient に接続を渡し、Greeter サービスのクライアントを作ります。以降はこの c を通じて RPC を呼び出します。
(4) RPC の呼び出し
ctx, cancel := context.WithTimeout(context.Background(), time.Second) |
指定した名前で SayHello を呼び出し、サーバからの応答をログ出力します。context.WithTimeout でタイムアウト付きのコンテキストを作っているため、一定時間(ここでは1秒)応答がなければ呼び出しが打ち切られます。gRPC ではこのように、呼び出しごとにコンテキストでタイムアウトやキャンセルを制御するのが基本です。
6. 実行:サーバとクライアントを動かす
実装ができたら動かしてみます。まず1つ目のターミナルでサーバを起動します。
$ go run greeter_server/main.go |
続いて、別のターミナルをもう1つ開いてクライアントを実行します。
$ go run greeter_client/main.go |
クライアント側に Greeting: Hello world と表示され、サーバ側のターミナルに Received: world と出力されれば成功です(defaultName が world の場合の例)。サーバとクライアントが gRPC 経由で通信できたことになります。
応用:サービスにメソッドを追加してみる
gRPC 開発の流れに慣れるため、サービスへ新しい RPC を1つ追加してみましょう。「もう一度挨拶する」SayHelloAgain を加えます。.proto の service ブロックを次のように変更します。
|
// 挨拶サービスの定義 |
.proto を変更したら、必ずコードを再生成します。生成しないと、追加したメソッドに対応する型やインターフェースが反映されません。手順3と同じコマンドを再実行します。
$ protoc --go_out=. --go_opt=paths=source_relative \ |
再生成すると GreeterServer インターフェースに SayHelloAgain が加わります。サーバ側にその実装を追加します。
func (s *server) SayHelloAgain(ctx context.Context, in *pb.HelloRequest) (*pb.HelloReply, error) { |
クライアント側でも、c.SayHello(...) と同様に c.SayHelloAgain(...) を呼び出すコードを足せば、新しい RPC を利用できます。このように「.proto を直す → 再生成する → 実装を足す」というサイクルが gRPC 開発の基本になります。
| よくある落とし穴 |
|---|
|
FAQ
Q1. protoc-gen-go と protoc-gen-go-grpc は何が違うのですか。両方必要ですか。
役割が異なります。protoc-gen-go は message から生成されるデータ型(リクエスト/レスポンスの構造体)を担当し、protoc-gen-go-grpc は service から生成されるクライアント・サーバ用のインターフェースを担当します。gRPC サービスを Go で扱うには、通常この両方が必要です。
Q2. なぜ古い grpc.Dial ではなく grpc.NewClient を使う例になっているのですか。
比較的新しい gRPC for Go では、接続(チャネル)の生成に grpc.NewClient を用いる方針が示されているためです。インターネット上の古い記事では grpc.Dial を使った例も多く見られますが、利用しているバージョンによって推奨 API が異なります。実装時は、手元のライブラリのバージョンと、それに対応する公式ドキュメントの記述に合わせるのが確実です。
ページの作成
親となるページを選択してください。
親ページに紐づくページを子ページといいます。
例: 親=スポーツ, 子1=サッカー, 子2=野球
子ページを親ページとして更に子ページを作成することも可能です。
例: 親=サッカー, 子=サッカーのルール
親ページはいつでも変更することが可能なのでとりあえず作ってみましょう!
子ページはありません
- Protocol Buffers
- 詳細説明付きクイックスタート
- Docker + Go言語 + gRPC で簡単なWebアプリケーションを作る その1
人気ページ
- 1 Eclipseで「サーバーに追加または除去できるリソースがありません。」の原因と対処法
- 2 tomcat の起動 / 停止ログと catalina.log・catalina.out の違い
- 3 JavaScript base URL 取得方法|window.location.origin と SSR/Node.js 対応
- 4 YouTube Data API v3 エラー一覧|403/400/404 の主要原因と切り分け
- 5 Spring Frameworkのアノテーション一覧
- 6 Laravel エラー一覧|500/Blade/DB 接続/ルーティングの代表エラー
- 7 3Dグラフィックスとは|モデリング/レンダリング/主要ソフトウェア (Blender / Maya)
- 8 【Spring】@Valueアノテーションとは
- 9 CATALINA_HOME の確認方法 (Linux / Mac)
- 10 【Spring】@Autowiredアノテーションとは
最近更新/作成されたページ
- IPv6とは|128bitアドレス・コロン16進表記/::省略・リンクローカル・SLAAC・デュアルスタック NEW 2026-06-22 12:34:44
- MAC アドレスフィルタリングの仕組みと限界 | ネットワーク入門 NEW 2026-06-22 12:19:10
- VPNとは|暗号トンネル・サイト間/リモートアクセス・IPsec/SSL-VPN/WireGuardを解説 NEW 2026-06-22 12:19:10
- WebRTC とは ブラウザ間 P2P の音声・映像・データ通信 | ネットワーク入門 NEW 2026-06-22 12:17:25
- HTTP/2 とは 多重化・HPACK・バイナリフレーム | ネットワーク入門 NEW 2026-06-22 12:17:25
- Web通信プロトコル入門 HTTP/2・HTTP/3・WebSocket・gRPC・WebRTC | ネットワーク入門 NEW 2026-06-22 12:17:25
- gRPC とは HTTP/2 + Protocol Buffers の高速 RPC | ネットワーク入門 NEW 2026-06-22 12:17:25
- HTTP/3 (QUIC) とは UDP ベースの低遅延 Web 通信 | ネットワーク入門 NEW 2026-06-22 12:17:25
- WebSocket とは 全二重リアルタイム通信 ws/wss | ネットワーク入門 NEW 2026-06-22 12:17:25
- 証明書と認証局(CA)とは|X.509・信頼チェーン・DV/OV/EV・失効(CRL/OCSP)を解説 NEW 2026-06-22 12:17:24
- ファイアウォールとは|パケットフィルタ・ステートフル・DMZ・次世代FW(L4/L7)を解説 NEW 2026-06-22 12:17:24
- iptables/nftablesとは|テーブル・チェーン・ルール例・永続化をLinux視点で解説 NEW 2026-06-22 12:17:24
- HAProxy とは frontend/backend と設定例 | ネットワーク入門 NEW 2026-06-22 12:17:24
- CDN とは エッジキャッシュ・TTL・Cloudflare/CloudFront | ネットワーク入門 NEW 2026-06-22 12:17:24
- TLS/SSLの仕組み|ハンドシェイク・暗号スイート・前方秘匿性・証明書検証をわかりやすく解説 NEW 2026-06-22 12:17:24
コメントを削除してもよろしいでしょうか?