2025年2月4日火曜日

Go言語入門(8)

興味本位でGo言語に触れてみようと思う。WSLでGoでgRPCをやってみる。64bit Windows実行ファイルを作って動作を確認することろまで。



なんで?ていうとgRPCもGoもgoogleが開発したものだから相性がいいはず。ってのと、WindowsでC++でgRPCするってなると、マイクロソフトコンパイラが必要になってCommunity EditionとBuild toolsをインストールするってなって、で、何度も触れているようにLicense Termsが気に食わないのでやだっ。WindowsでMSYS+mingwとかWSL+mingwでもgRPCができるのかもしれないとは思っている(実は途中までやって挫折している)けど、先にGoでやった方が理解が深まるかもしれないと思っている。
参考サイトは総本山(https://grpc.io/)
では、総本家のGoをクリックしてQuick startを単にその説明をたどっていく(<--まぁちゃんとできるようになったゾっていう記録だけ)。

Prerequisites
Goを入れんかいって書いてあるけど、これは入っている。
Protocol buffer compilerを入れんかいって書いてある。"Protocol Buffer Compiler Installation"をつついて、
apt install -y protobuf-compiler
protoc --version
ってやれって書いてあるので、そのままやってみる。Warningにバージョンが大事だ的な記述があるけど、まずは入れてみろってことやな。
3以上じゃないといかんよって書いてあるのでOKってことで。
で、Quick startに戻って、Go pluginsってのを入れろって書いてあるので言われた通りにやってみる。
go install google.golang.org/protobuf/cmd/protoc-gen-go@latest
go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@latest
(なんかカレントディレクトリに入れちまわないだろうかとls撃ってるのは気にしない)
で、PATHを設定しろって書いてある。
export PATH="$PATH:$(go env GOPATH)/bin"
これが"go env GOPATH"ってなんや?ってなるけど、$HOMEのgo/binらしい。なので、 export PATH="$PATH:$HOME/go/bin"

Get the example code
gitからダウンロードしてexampleフォルダに移動しろって書いてある。git cloneすると、カレントディレクトリにぶっこんでくれるので、そこはうまいことやらんといかん。
git clone -b v1.70.0 --depth 1 https://github.com/grpc/grpc-go
cd grpc-go/examples/helloworld

Run the example
単に実行しろって書いてある。
go run greeter_server/main.go
で別のターミナルで go run greeter_client/main.go
そすっと、
こんな感じであっさり動いちゃう。ほかの言語のQuick startはまぁまぁしんどいのにやっぱGoびいきだねきっと。

Update the gRPC service
英語なのでもう読むのがしんどくなってきたが、helloworld/helloworld.protoを編集してprotocしろってことらしい。

helloworld/helloworld.proto
  1. // Copyright 2015 gRPC authors.
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14.  
  15. syntax = "proto3";
  16.  
  17. option go_package = "google.golang.org/grpc/examples/helloworld/helloworld";
  18. option java_multiple_files = true;
  19. option java_package = "io.grpc.examples.helloworld";
  20. option java_outer_classname = "HelloWorldProto";
  21.  
  22. package helloworld;
  23.  
  24. // The greeting service definition.
  25. service Greeter {
  26.   // Sends a greeting
  27.   rpc SayHello (HelloRequest) returns (HelloReply) {}
  28.   // Sends another greeting
  29.   rpc SayHelloAgain (HelloRequest) returns (HelloReply) {}
  30. }
  31.  
  32. // The request message containing the user's name.
  33. message HelloRequest {
  34.   string name = 1;
  35. }
  36.  
  37. // The response message containing the greetings
  38. message HelloReply {
  39.   string message = 1;
  40. }
SayHelloAgainってのを追加したわけだ。

protoc --go_out=. --go_opt=paths=source_relative --go-grpc_out=. --go-grpc_opt=paths=source_relative helloworld/helloworld.proto
エラー吐いてないからいいんやろ、きっと。総本山によると、これで、helloworld/helloworld.pb.goとhelloworld/helloworld_grpc.pb.goができるらしい。心配ならタイムスタンプを確認する。

Update and run the application

greeter_server/main.go
  1. /*
  2.  *
  3.  * Copyright 2015 gRPC authors.
  4.  *
  5.  * Licensed under the Apache License, Version 2.0 (the "License");
  6.  * you may not use this file except in compliance with the License.
  7.  * You may obtain a copy of the License at
  8.  *
  9.  * http://www.apache.org/licenses/LICENSE-2.0
  10.  *
  11.  * Unless required by applicable law or agreed to in writing, software
  12.  * distributed under the License is distributed on an "AS IS" BASIS,
  13.  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14.  * See the License for the specific language governing permissions and
  15.  * limitations under the License.
  16.  *
  17.  */
  18.  
  19. // Package main implements a server for Greeter service.
  20. package main
  21.  
  22. import (
  23.     "context"
  24.     "flag"
  25.     "fmt"
  26.     "log"
  27.     "net"
  28.     "google.golang.org/grpc"
  29.     pb "google.golang.org/grpc/examples/helloworld/helloworld"
  30. )
  31.  
  32. var (
  33.     port = flag.Int("port", 50051, "The server port")
  34. )
  35. // server is used to implement helloworld.GreeterServer.
  36. type server struct {
  37.     pb.UnimplementedGreeterServer
  38. }
  39.  
  40. // SayHello implements helloworld.GreeterServer
  41. func (s *server) SayHello(_ context.Context, in *pb.HelloRequest) (*pb.HelloReply, error) {
  42.     log.Printf("Received: %v", in.GetName())
  43.     return &pb.HelloReply{Message: "Hello " + in.GetName()}, nil
  44. }
  45. func (s *server) SayHelloAgain(ctx context.Context, in *pb.HelloRequest) (*pb.HelloReply, error) {
  46.     return &pb.HelloReply{Message: "Hello again " + in.GetName()}, nil
  47. }
  48. func main() {
  49.     flag.Parse()
  50.     lis, err := net.Listen("tcp", fmt.Sprintf(":%d", *port))
  51.     if err != nil {
  52.         log.Fatalf("failed to listen: %v", err)
  53.     }
  54.     s := grpc.NewServer()
  55.     pb.RegisterGreeterServer(s, &server{})
  56.     log.Printf("server listening at %v", lis.Addr())
  57.     if err := s.Serve(lis); err != nil {
  58.         log.Fatalf("failed to serve: %v", err)
  59.     }
  60. }
SayHelloAgainを追加。

greeter_client/main.go
  1. /*
  2.  *
  3.  * Copyright 2015 gRPC authors.
  4.  *
  5.  * Licensed under the Apache License, Version 2.0 (the "License");
  6.  * you may not use this file except in compliance with the License.
  7.  * You may obtain a copy of the License at
  8.  *
  9.  * http://www.apache.org/licenses/LICENSE-2.0
  10.  *
  11.  * Unless required by applicable law or agreed to in writing, software
  12.  * distributed under the License is distributed on an "AS IS" BASIS,
  13.  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14.  * See the License for the specific language governing permissions and
  15.  * limitations under the License.
  16.  *
  17.  */
  18.  
  19. // Package main implements a client for Greeter service.
  20. package main
  21.  
  22. import (
  23.     "context"
  24.     "flag"
  25.     "log"
  26.     "time"
  27.     "google.golang.org/grpc"
  28.     "google.golang.org/grpc/credentials/insecure"
  29.     pb "google.golang.org/grpc/examples/helloworld/helloworld"
  30. )
  31.  
  32. const (
  33.     defaultName = "world"
  34. )
  35.  
  36. var (
  37.     addr = flag.String("addr", "localhost:50051", "the address to connect to")
  38.     name = flag.String("name", defaultName, "Name to greet")
  39. )
  40.  
  41. func main() {
  42.     flag.Parse()
  43.     // Set up a connection to the server.
  44.     conn, err := grpc.NewClient(*addr, grpc.WithTransportCredentials(insecure.NewCredentials()))
  45.     if err != nil {
  46.         log.Fatalf("did not connect: %v", err)
  47.     }
  48.     defer conn.Close()
  49.     c := pb.NewGreeterClient(conn)
  50.     // Contact the server and print out its response.
  51.     ctx, cancel := context.WithTimeout(context.Background(), time.Second)
  52.     defer cancel()
  53.     r, err := c.SayHello(ctx, &pb.HelloRequest{Name: *name})
  54.     if err != nil {
  55.         log.Fatalf("could not greet: %v", err)
  56.     }
  57.     log.Printf("Greeting: %s", r.GetMessage())
  58.     r, err = c.SayHelloAgain(ctx, &pb.HelloRequest{Name: *name})
  59.     if err != nil {
  60.         log.Fatalf("could not greet: %v", err)
  61.     }
  62.     log.Printf("Greeting: %s", r.GetMessage())
  63. }
c.SayHelloAgain以降を追加。
んでもって、実行してみる。
go run greeter_server/main.go
で別のターミナルで go run greeter_client/main.go --name=Alice
そすっと、
まぁこんな感じでうまくいく(そりゃあたりまえよ)。
Windows実行ファイルとしてコンパイルしてみる。
cd greeter_server
GOOS=windows GOARCH=amd64 go build -o greeter_server.exe main.go
ls -la
cd ../greeter_client
GOOS=windows GOARCH=amd64 go build -o greeter_client.exe main.go
ls -la
cd ..
いちおうできた風。
アクセス許可のダイアログが出るので許可してっと。とりあえず動いている風。
これがWindowsで動くかどうか。
\\WSL$からWSL内をほじっていって、実行ファイルをコピーしてDocuments下あたりにコピペする。で、ファイルのプロパティで実行許可を与えた。
実行ファイルがあるフォルダのアドレスバーにcmdって入れるとコマンドプロンプト画面が出る。2つ出す。で、実行。
うごいたー。

やっぱりgRPCやるのにGoは適している!<--そりゃそうだろ
WSLでGOOSとGOARCHで指定するだけでWindows実行ファイルができちゃうってのが大変すばらしいよ。

0 件のコメント:

コメントを投稿