安装protoc

地址:https://github.com/protocolbuffers/protobuf/releases

安装protoc-gen-go

1
go get -u github.com/golang/protobuf/protoc-gen-go

安装grpc

1
2
3
4
git clone https://github.com/grpc/grpc-go.git $GOPATH/src/google.golang.org/grpc

cd $GOPATH/src/grpc/cmd/protoc-gen-go-grpc
go install

HelloWorld

  • 创建项目目录
1
2
3
4
5
6
7
8
9
10
11
mkdir hello-world
mkdir -p hello-world/cmd
mkdir -p hello-world/protos
mkdir -p hello-world/sh


目录结构
└─hello-world
├─cmd
├─protos
└─sh
  • 编辑proto文件
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
> vim hello-world/cmd/hello-world.proto


syntax="proto3";
package protos;

option go_package="./protos";

service HelloWorld{
rpc Send(SendRequest) returns(SendResponse){}
rpc Count(CountRequest) returns (CountResponse){}
}

message SendRequest{
string msg = 1;
}

message SendResponse{
int32 code = 1;
string msg = 2;
repeated SendRequest data = 3;
}

message CountRequest{
int32 a = 1;
int32 b = 2;
}

message CountResponse{
int32 code = 1;
string msg = 2;
int32 sum = 3;
}
  • 编辑代码生成脚本
1
2
3
4
5
6
7
8
9
10
> vim hello-world/sh/gen.sh


#!/usr/bin/env bash

protoDir="../protos"
outDir="../"

protoc -I ${protoDir}/ ${protoDir}/*proto --go_out=${outDir}
protoc -I ${protoDir}/ ${protoDir}/*proto --go-grpc_out=${outDir}
  • 生成服务端和客户端代码
1
2
cd hello-world/sh
./gen.sh
  • 编辑服务端代码
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
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
> vim hello-world/cmd/server.go

package main

import (
pb "app/protos"
"context"
"fmt"
"log"
"net"

"google.golang.org/grpc"
"google.golang.org/grpc/reflection"
)

const (
port = ":50051"
)

type server struct {
pb.UnimplementedHelloWorldServer
}

func (s *server) Send(ctx context.Context, request *pb.SendRequest) (*pb.SendResponse, error) {
fmt.Println("client send msg: ", request.Msg)
return &pb.SendResponse{
Code: 0,
Msg: "success",
Data: []*pb.SendRequest{
&pb.SendRequest{
Msg: request.Msg + " response",
},
},
}, nil
}

func (s *server) Count(ctx context.Context, request *pb.CountRequest) (*pb.CountResponse, error) {
fmt.Println("client count A:", request.A, " client count B: ", request.B)
return &pb.CountResponse{
Code: 0,
Msg: "success",
Sum: request.A + request.B,
},nil
}

func main() {
listen, err := net.Listen("tcp", port)
if err != nil {
log.Fatalf("listener error: $v", err)
}

s := grpc.NewServer()
pb.RegisterHelloWorldServer(s, &server{})

reflection.Register(s)

if err := s.Serve(listen); 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
39
40
41
42
43
44
package main

import (
pb "app/protos"
"context"
"fmt"
"google.golang.org/grpc"
"log"
"time"
)

const (
address = "localhost:50051"
)

func main() {
conn, err := grpc.Dial(address, grpc.WithInsecure(), grpc.WithBlock())
if err != nil {
log.Fatalf("did not connect: %v", err)
}
defer conn.Close()

c := pb.NewHelloWorldClient(conn)

ctx, cancel := context.WithTimeout(context.Background(), time.Second)
defer cancel()

r, err := c.Send(ctx, &pb.SendRequest{
Msg: "Hello World",
})
if err != nil {
log.Fatalf("send error: %v", err)
}
fmt.Println("send response", r)

countResponse,err := c.Count(ctx, &pb.CountRequest{
A:5,
B:10,
})
if err != nil {
log.Fatalf("count error: %v", err)
}
fmt.Println("count response", countResponse)
}
  • 运行服务端和客户端
1
2
3
4
5
6
7
8
9
cd hello-world

go mod init

go mod tidy

go run cmd/server.go

go run cmd/client.go
  • 使用grpcui
1
2
3
4
5
6
7
8
9
# 安装
go get github.com/fullstorydev/grpcui
go install github.com/fullstorydev/grpcui/cmd/grpcui


# 使用
grpcui -plaintext localhost:12345

## localhost:12345 为 grpc 服务端监听地址

参考地址: