Go言語でgRPCに入門してみたかった...
ふとGoでgRPCをやってみたくなって,こちらの記事を参考にハンズオンをやってみました.
ただ,すんなりとはいかなかったので自分も記事を書いてみることにしました.
触れないこと
gRPCとはなにか
RESTと比較して何が良いか
Goの使い方
ここらへんは元記事を参考にしてください.
ハンズオン!
前提としてGo(1.6 or higher)がインストール済みとします.
色々インストール
まずはgrpcをインストール
$ go get -u google.golang.org/grpc
次に Protocol Buffers v3をインストール
$ brew install protobuf
$ exec $SHELL -l
そして,Protocol Buffers の Go プラグインもインストール
$ go get -u github.com/golang/protobuf/protoc-gen-go
go: module github.com/golang/protobuf is deprecated: Use the "google.golang.org/protobuf" module instead.
早速つまづきました.どうやら "github.com/golang/protobuf" は非推奨のようです.代わりに "google.golang.org/protobuf" を使えということらしいです🤔
gRPCの公式Goチュートリアルを見てみると
$ go install google.golang.org/protobuf/cmd/protoc-gen-go@v1.28
$ go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@v1.2
$ export PATH="$PATH:$(go env GOPATH)/bin"
で Protocol Buffers の Go プラグインをインストールしているのでそれに習います.
これでとりあえずインストール完了
protoファイルからコードを自動生成
protoファイルを書いていきます.
元記事とはディレクトリ構成を変えて /chat/chat.proto に proto ファイルを作成します
syntax = "proto3";
package chat;
option go_package="./chat";
message Message {
string body = 1;
}
service ChatService {
rpc SayHello(Message) returns (Message) {}
}
元記事のコードに "go_package" オプションを加えています.
これは元記事の状態でGoのgRPCのコードを生成しようとすると,"unable to determine Go import path for "chat/chat.proto" と言われるので追加しました.詳しいことはまだ調べられてないです.
Go固有のgRPCコードを生成していきます.元記事に従って
$ protoc --go_out=plugins=grpc:chat ./chat/chat.proto
とすると,"--go_out: protoc-gen-go: plugins are not supported; use 'protoc --go-grpc_out=...' to generate gRPC"と怒られるのでこちらも公式チュートリアルを参考に
$ protoc --go_out=. --go_opt=paths=source_relative \
--go-grpc_out=. --go-grpc_opt=paths=source_relative \
./chat/chat.proto
を実行します.
すると,/chat 以下に chat.pb.go と chat_grpc.pb.go が生成されます.
Goのコードを作成
/chat/chat.go にメッセージを返すメソッドを定義していきます.
package chat
import (
"context"
"log"
)
type Server struct {
UnimplementedChatServiceServer
}
func (s Server) SayHello(ctx context.Context, in *Message) (*Message, error) {
log.Printf("Receive message body from client: %s", in.Body)
return &Message{Body: "Hello From the server"}, nil
}
次に /server.go を作成します.
package main
import (
"GrpcSample/chat"
"google.golang.org/grpc"
"log"
"net"
)
func main() {
lis, err := net.Listen("tcp", ":9000")
if err != nil {
log.Fatalf("failed to listen: %v", err)
}
s := chat.Server{}
grpcServer := grpc.NewServer()
chat.RegisterChatServiceServer(grpcServer, &s)
if err := grpcServer.Serve(lis); err != nil {
log.Fatalf("failed to serve: %s", err)
}
}
最後にサーバーを起動します.
$ go run server.go
Go gRPC Beginners Tutorial!
gRPCクライアントを作成
元記事の通りに /client.go を作成します.
package main
import (
"GrpcSample/chat"
"context"
"google.golang.org/grpc"
"google.golang.org/grpc/credentials/insecure"
"log"
)
func main() {
var conn *grpc.ClientConn
conn, err := grpc.Dial(":9000", grpc.WithTransportCredentials(insecure.NewCredentials()))
if err != nil {
log.Fatalf("did not connect: %s", err)
}
defer conn.Close()
c := chat.NewChatServiceClient(conn)
resp, err := c.SayHello(context.Background(), &chat.Message{
Body: "Hello From Client!",
})
if err != nil {
log.Fatalf("Error when calling SyaHello: %s", err)
}
log.Printf("Responce from server: %s", resp.Body)
}
これを実行して
$ go run ./client.go
2022/05/28 10:40:08 Responce from server: Hello From the server
となると成功です😀
おわりに
サクッと Go で gRPC を試せるように記事にしてくれた先人に感謝です.(この記事の内容も1年後とかには動かなくなっているんだろうなぁ…)