1 下载插件
$ 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
2 添加到环境变量
vi ~/.profile, 添加此行到文件末尾
export PATH=$PATH:$GOPATH/bin
3 proto文件
syntax = "proto3";
// _grpc.pb.go文件生成路径为./ ; 生成的go文件package名为proto
option go_package = "./;proto";
service Greeter {
rpc SayHello (HelloRequest) returns (HelloReply);
}
message HelloRequest {
string name = 1;
}
message HelloReply {
string message = 1;
}
4 根据proto生成go文件
(1) protoc命令详解
protoc -I=. —go_out=./ —go-grpc_out=./ /proto/user.proto
- I: 指定proto文件和导入proto文件的搜索根路径, 可以指定多个
若I是/home/ws/code, 导包语句是 import “app/user/rpc/user.proto” 那么导入的包的全路径就是
/home/ws/code/app/user/rpc/user.proto
等价于—proto_path=.
- go_out: 指定pb.go代码的生成位置
—go_out 参数的写法是,参数之间用逗号隔开, 最后加上冒号来指定代码目录架构的生成位置
例如:—go_out=plugins=grpc,paths=import:.
paths 参数有两个选项,import 和 source_relative 。
- 默认为 import:. ,代表把pb.go生成到option go_package里指定的目录
- source_relative:. 代表把pb.go生成到和proto同级
pugins=grpc 现在已经不支持了, 要改用go-grpc_out
- go-grpc_out: 指定_grpc.pb.go代码(stub)的生成位置
若为./, 则把_grpc.pb.go生成到option go_package里指定的目录
(2) 去除omitempty
// 去除proto中的json的omitempty
mac: sed -i "" 's/,omitempty//g' *.pb.go
linux: sed -i 's/,omitempty//g' *.pb.go
go get github.com/srikrsna/protoc-gen-gotag
protoc --gotag_out=auto="json-as-camel":. user.proto
生成了两个文件
- hello.pb.go: 定义了协议, 即请求与响应的消息结构
- hello_grpc.pb.go: 定义了stub, 即grpc的client stub和server stub
5 server.go
```go package main
import ( “context” “google.golang.org/grpc” “net” “testgrpc/proto” )
type Server struct { proto.UnimplementedGreeterServer }
func (s Server) SayHello(ctx context.Context, request proto.HelloRequest) (*proto.HelloReply, error) { return &proto.HelloReply{ Message: “hello” + request.Name, }, nil }
func main() { g := grpc.NewServer() proto.RegisterGreeterServer(g, &Server{}) listener, err := net.Listen(“tcp”, “:8080”) if err != nil { panic(“failed to listen: “ + err.Error()) } _ = g.Serve(listener) }
<a name="JWa5o"></a>
# 6 client.go
```go
package main
import (
"context"
"google.golang.org/grpc"
"google.golang.org/grpc/credentials/insecure"
"log"
"testgrpc/proto"
"time"
)
func main() {
addr := "localhost:8080"
name := "world"
// Set up a connection to the server.
conn, err := grpc.Dial(addr, grpc.WithTransportCredentials(insecure.NewCredentials()))
if err != nil {
log.Fatalf("did not connect: %v", err)
}
defer conn.Close()
c := proto.NewGreeterClient(conn)
// Contact the server and print out its response.
ctx, cancel := context.WithTimeout(context.Background(), time.Second)
defer cancel()
r, err := c.SayHello(ctx, &proto.HelloRequest{Name: name})
if err != nil {
log.Fatalf("could not greet: %v", err)
}
log.Printf("Greeting: %s", r.GetMessage())
}