golang使用grpc

617 阅读2分钟

准备环境

安装protobuf环境

参考golang使用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

参考:

gRPC 官方文档中文版

go版本

go-grpc-middleware

gRPC详细入门教程

gRPC详细入门教程,Golang/Python/PHP多语言讲解