やりたいこと
Go言語gRPCのクライアント⇔サーバ通信をローカルで試す。
1.インストール準備
・protocインストール(こちらを参照)
go install google.golang.org/protobuf/cmd/protoc-gen-go@latest
go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@latest
2.プロジェクト&各ディレクトリ作成
mkdir example
mkdir -p example/proto
mkdir -p example/grpc_sample
mkdir -p example/server
mkdir -p example/client
3.go.mod作成
cd example
go mod init github.com/example
2.protoファイル作成
cd proto
以下のsample.protoをprotoディレクトリに保存
syntax = "proto3";
package sample;
option go_package = "../grpc_sample";
message Message {
string body = 1;
}
service SampleService {
rpc GetData(Message) returns (Message) {}
}
3.protoファイルからprotoc-gen-go/protoc-gen-go-grpcファイル生成
protoc --go_out=. --go-grpc_out=require_unimplemented_servers=false:. sample.proto
サーバープログラム作成
cd ../server
以下のmain.goをserverディレクトリに保存
package main
import (
"github.com/example/grpc_sample"
"golang.org/x/net/context"
"google.golang.org/grpc"
"log"
"net"
)
func main() {
log.Print("main start")
// 9000番ポートでクライアントからのリクエストを受け付けるようにする
listen, err := net.Listen("tcp", ":9000")
if err != nil {
log.Fatalf("failed to listen: %v", err)
}
grpcServer := grpc.NewServer()
// Sample構造体のアドレスを渡すことで、クライアントからGetDataリクエストされると
// GetDataメソッドが呼ばれるようになる
grpc_sample.RegisterSampleServiceServer(grpcServer, &Sample{})
// 以下でリッスンし続ける
if err := grpcServer.Serve(listen); err != nil {
log.Fatalf("failed to serve: %s", err)
}
log.Print("main end")
}
type Sample struct {
name string
}
func (s *Sample) GetData(
ctx context.Context,
message *grpc_sample.Message,
) (*grpc_sample.Message, error) {
log.Print(message.Body)
return &grpc_sample.Message{Body: "レスポンスデータ"}, nil
}
クライアントプログラム作成
cd ../client
以下のmain.goをclientディレクトリに保存
package main
import (
"github.com/example/grpc_sample"
"golang.org/x/net/context"
"google.golang.org/grpc"
"log"
)
func main() {
var conn *grpc.ClientConn
conn, err := grpc.Dial(":9000", grpc.WithInsecure())
if err != nil {
log.Fatalf("did not connect: %s", err)
}
c := grpc_sample.NewSampleServiceClient(conn)
response, err := c.GetData(context.Background(), &grpc_sample.Message{Body: "送信データ"})
if err != nil {
log.Fatalf("Error when calling SayHello: %s", err)
}
log.Print(response.Body)
defer conn.Close()
}
パッケージをダウンロード
cd ../
go mod tidy
動作確認