Go GRPC 入门

安装准备工作

  1. 安装protoc go相关的编译器:
1
2
3
sudo apt-get install protoc
$ go install google.golang.org/protobuf/cmd/protoc-gen-go@v1.26
$ go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@v1.1
  1. 更新环境变量:
1
$ export PATH="$PATH:$(go env GOPATH)/bin"
  1. 下载 grpc-go, 因为众所周知的原因, 需要从 Github 下载, 再放到 google.golang.org
1
2
$ cd /home/levizheng/go/src/google.golang.org
$ git clone -b v1.41.0 https://github.com/grpc/grpc-go grpc-go

实操

实现一个 mygrpc 的 项目, 目录树如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
$:~/go/src/mygrpc>tree
.
├── client
│ ├── main
│ └── main.go
├── go.mod
├── go.sum
├── helloworld
│ ├── helloworld_grpc.pb.go
│ ├── helloworld.pb.go
│ └── helloworld.proto
├── helloworld.bak
└── svr
├── main
└── main.go
  • 写 Proto & 生成代码

在 mygrpc 目录下 生成 proto.go, proto_grpc.pb.go

1
2
3
mkdir helloworld;
touch helloworld.proto
$ protoc --go_out=. --go_opt=paths=source_relative --go-grpc_out=. --go-grpc_opt=paths=source_relative helloworld/helloworld.proto

需要修改 helloworld_grpc.pb.go 的 package 为 helloworld, 不然后面编译不过

  • server & client 的代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
package main
import (
"context"
"log"
"net"
"google.golang.org/grpc"
pb "mygrpc/helloworld"
)

const (
port = ":50051"
)


// server is used to implement helloworld.GreeterServer.
type server struct {
pb.UnimplementedGreeterServer
}


// SayHello implements helloworld.GreeterServer
func (s *server) SayHello(ctx context.Context, in *pb.HelloRequest) (*pb.HelloReply, error) {
log.Printf("Received: %v", in.GetName())
return &pb.HelloReply{Message: "Hello " + in.GetName()}, nil
}


func main() {
lis, err := net.Listen("tcp", port)
if err != nil {
log.Fatalf("failed to listen: %v", err)
}
s := grpc.NewServer()
pb.RegisterGreeterServer(s, &server{})
log.Printf("server listening at %v", lis.Addr())
if err := s.Serve(lis); err != nil {
log.Fatalf("failed to serve: %v", err)
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
package main

import (
"context"
"log"
"os"
"time"
"google.golang.org/grpc"
pb "mygrpc/helloworld"
)

const (
address = "localhost:50051"
defaultName = "world"
)

func main() {
// Set up a connection to the server.
conn, err := grpc.Dial(address, grpc.WithInsecure(), grpc.WithBlock())
if err != nil {
log.Fatalf("did not connect: %v", err)
}
defer conn.Close()
c := pb.NewGreeterClient(conn)

// Contact the server and print out its response.
name := defaultName
if len(os.Args) > 1 {
name = os.Args[1]
}
ctx, cancel := context.WithTimeout(context.Background(), time.Second)
defer cancel()
r, err := c.SayHello(ctx, &pb.HelloRequest{Name: name})
if err != nil {
log.Fatalf("could not greet: %v", err)
}
log.Printf("Greeting: %s", r.GetMessage())
}
  • 在 mygrpc 目录下生成 go.mod , 使其顺利编译
1
2
3
4
5
6
cd ~/go/src/mygrpc;
go mod init mygrpc
go mod tidy

go build svr/main.go
go build svr/client.go