新版grpc-go与旧版稍有不同

protoc-gen-go/protoc-gen-go-grpc安装
cmd 执行

1
2
$ go install google.golang.org/protobuf/cmd/protoc-gen-go@latest  
$ go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@latest

创建proto文件,如message.proto

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
syntax = "proto3";

// 包名
package message;

// 指定输出 go 语言的源码到哪个目录以及文件名称
// 最终在 message.proto 目录生成 message.pb.go
option go_package = "./;protoc"; //指定package为proto不然会生成package __ 导致无法引包,./为生成到 -I 参数指定的目录,也可以指定其他目录用于生成"-I指定目录+其他目录"

service PolicyService{
rpc RpcPolicy(Request) returns (Response){}
}

// 函数参数
message Request{
string jsonStr = 1;
}

// 函数返回值
message Response{
string backJson = 1;
}

转换proto到对应的变成语言源文件
protoc --proto_path=D:\GoProject\protoc\ --go_out=D:\GoProject\protoc\ D:\GoProject\protoc\message.proto

生成gRPC服务语言源文件
protoc --proto_path=D:\GoProject\protoc\ --go-grpc_out=D:\GoProject\protoc\ D:\GoProject\protoc\message.proto

–proto_path 指定proto文件路径
–go_out 指定生成的go文件的输出路径
–go-grpc_out 指定gRPC服务生成的go文件的输出路径
指定message.proto文件路径

生成代码后可以在 message_grpc.pb.go 文件中找到定义的关键的接口

1
2
3
4
5
6
7
8
type PolicyServiceClient interface {
RpcPolicy(ctx context.Context, in *Request, opts ...grpc.CallOption) (*Response, error)
}

type PolicyServiceServer interface {
RpcPolicy(context.Context, *Request) (*Response, error)
mustEmbedUnimplementedPolicyServiceServer()
}

要实现 proto 中的服务,则需要我们实现 PolicyServiceServer 接口,要编写 客户端,则需要实现 PolicyServiceClient

创建grpc服务端

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
package main

import (
"context"
"fmt"
"google.golang.org/grpc"
"google.golang.org/grpc/reflection"
"log"
"net"
)
import "protoc" // 引入生成的go文件


// 新版的grpc需要实现mustEmbedUnimplementedPolicyServiceServer()方法,因此继承PolicyServiceServer然后重写RpcPolicy
type MyGrpcServer struct {
protoc.PolicyServiceServer // 继承PolicyServiceServer
}

// 重写RpcPolicy
func (myserver *MyGrpcServer) RpcPolicy(context context.Context, request *protoc.Request) (*protoc.Response, error) {
fmt.Println("receive grpc request, args is:", request)
response := protoc.Response{RespJson: `{"Code": 6}`}
return &response, nil
}

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

grpcServer := grpc.NewServer()

protoc.RegisterPolicyServiceServer(grpcServer, &MyGrpcServer{})
reflection.Register(grpcServer)
err = grpcServer.Serve(listener)
if err != nil {
log.Fatalf("failed")
}

}

创建grpc客户端

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 (
"bufio"
"context"
"google.golang.org/grpc"
"google.golang.org/grpc/credentials/insecure"
"log"
"protoc"
"os"
)

func main() {
conn, err := grpc.Dial("127.0.0.1:8028", grpc.WithTransportCredentials(insecure.NewCredentials()))
if err != nil {
log.Fatalf("connect gRPC error.", err)
}

defer func(conn *grpc.ClientConn) {
err := conn.Close()
if err != nil {

}
}(conn)

grpcClient := protoc.NewPolicyServiceClient(conn)
request := protoc.Request{
ReqJson: `{"Code": 7}`,
}

reader := bufio.NewReader(os.Stdin)

for {
response, err := grpcClient.RpcPolicy(context.Background(), &request)
if err != nil {
log.Fatalf("send req error, because:", err)
}
log.Println(response)
_, _, err = reader.ReadLine()
if err != nil {
return
}
}
}

执行go build进行编译两个端,然后client端按回车进行发送测试。
参考文章