見出し画像

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年後とかには動かなくなっているんだろうなぁ…)

この記事が気に入ったらサポートをしてみませんか?