准备环境
安装protobuf环境
安装gRpc环境
go get google.golang.org/grpc
编写proto文件
- 目录格式
syntax = "proto3";
package lightweight;
service Gym {
rpc BodyBuilding (Person) returns (Reply){
}
}
message Person{
string name = 1;
repeated string actions = 2;
}
message Reply {
int32 code = 1;
string msg = 2;
}
编译proto文件生成go文件
进到proto文件的目录
protoc --go_out=plugins=grpc:../lightweight/. gym.proto
生成的go文件会放在lightweight目录下,gym.pb.go
编译成生的go文件关键几个函数
这个注册函数需要服务器开启grpc服务后,把服务端的server注册进去,所以我们自己需要实现GymServer
这个接口
func RegisterGymServer(s *grpc.Server, srv GymServer) {
s.RegisterService(&_Gym_serviceDesc, srv)
}
- GymServer 接口:自己需要实现
GymServer
这个接口,重写BodyBuilding方法
// GymServer is the server API for Gym service.
type GymServer interface {
BodyBuilding(context.Context, *Person) (*Reply, error)
}
- 客户端 客户端需要打开grpc服务通道,需要跟服务器对应上相同的服务端口
// GymClient is the client API for Gym service.
type GymClient interface {
BodyBuilding(ctx context.Context, in *Person, opts ...grpc.CallOption) (*Reply, error)
}
func NewGymClient(cc grpc.ClientConnInterface) GymClient {
return &gymClient{cc}
}
func (c *gymClient) BodyBuilding(ctx context.Context, in *Person, opts ...grpc.CallOption) (*Reply, error) {
out := new(Reply)
err := c.cc.Invoke(ctx, "/lightweight.Gym/BodyBuilding", in, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
编写服务器端
package main
import (
"context"
"fmt"
pb "github.com/example/grpc-demo/lightweight"
"google.golang.org/grpc"
"log"
"net"
)
const (
port = ":50051"
)
type Server struct {
pb.UnimplementedGymServer
}
func (s *Server) BodyBuilding(ctx context.Context, person *pb.Person) (*pb.Reply, error) {
fmt.Printf("%s 正在健身,动作:%s \n", person.Name, person.Actions)
return &pb.Reply{Code: 0, Msg: "ok"}, nil
}
func main() {
lis, err := net.Listen("tcp", port)
if err != nil {
log.Fatalf("failed to listen: %v", err)
}
s := grpc.NewServer()
pb.RegisterGymServer(s, &Server{})
if err := s.Serve(lis); err != nil {
log.Fatalf("failed to serve: %v", err)
}
}
编写客户端
package main
import (
"context"
"fmt"
pb "github.com/example/grpc-demo/lightweight"
"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.NewGymClient(conn)
ctx, cancelFunc := context.WithTimeout(context.Background(), time.Second)
defer cancelFunc()
r, err := c.BodyBuilding(ctx, &pb.Person{
Name: "daxiongdi",
Actions: []string{"卧推", "硬拉", "深蹲"},
})
if err != nil {
log.Fatalf("error: %v", err)
}
fmt.Printf("code: %d, msg: %s", r.Code, r.Msg)
}
启动,运行
//启动服务器
go run gym_server.go
//启动客户端
go run gym_client.go
打印
daxiongdi 正在健身,动作:[卧推 硬拉 深蹲]
注意:
此项目用了go moudle, 在项目中引入包的时候会有个前缀github.com/example/grpc-demo
go init mod github.com/example/grpc-demo
go tidy
go mod vendor