1、新建初始化go项目,目录为grpc
2、新建pb_file目录,编写.proto文件
在pb_file目录下新建一个定义相关服务的proto文件,例如我创建一个product.proto,代码如下:
product.proto
syntax="proto3";
option go_package="../service";
package service;
//定义request model
message ProductRequest{
int32 prod_id=1;
}
//定义response model
message ProductResponse{
int32 prod_stock=1;
}
//定义一个服务
service ProductService{
//定义方法
rpc GetProductStock(ProductRequest) returns (ProductResponse);
}
3、生成 gRPC 的go代码
从终端进入grpc/pb_file目录下,用以下命令编译product.proto文件来生成需要的go代码。
protoc --go_out=. --go-grpc_out=. .\product.proto
可观察到项目工程下新增了一个service目录,并且该目录下生成了相应服务的golang代码!
此处注意,进行以上步骤前需要到github上下载相关protoc,下载后配置环境变量,然后执行protoc --version。
输出类似以下信息则安装成功,否则卸载重新安装
C:\Users\xxx>protoc --version
libprotoc 23.4
此外,如果此前未下载go编译proto的相关插件,则还需在终端运行以下命令进行下载!
go get -u google.golang.org/grpc
go install google.golang.org/protobuf/cmd/protoc-gen-go
go install google.golang.org/grpc/cmd/protoc-gen-go-grpc
4、编写grpc服务端
在项目工程下新建grpc_server,并且在该目录之下新建grpc_server.go文件,编写grpc_server.go。
在该文件中,首先需要获取一个获取grpc服务端(被调用方)rpcServer,然后将该rpcServer注册到相应的结构体上,此时通过.proto文件生成的相应代码里的RegisterProductServiceServer()函数进行注册!如下图所示,该函数接收以下参数作为变量!
并且接收的参数srv ProductServiceServer,追踪过去(如图所示),可以发现是一个接口,因此我们注册到的结构体应该实现图中所示接口里的方法,才能作为参数传入,将rpcServer映射到相应的结构体上。
因此,需要在service目录下,新建一个product.go文件,编写相关的结构体和方法实现,product.go代码如下:
package service
import "context"
type productService struct {
}
func (p *productService) mustEmbedUnimplementedProductServiceServer() {
//TODO implement me
panic("implement me")
}
var ProductService = &productService{}
func (p *productService) GetProductStock(context context.Context, request *ProductRequest) (*ProductResponse, error) {
//实现具体逻辑
stock := p.GetStockById(request.ProdId)
return &ProductResponse{
ProdStock: stock,
}, nil
}
func (p *productService) GetStockById(id int32) int32 {
return id
}
最终,完成grpc_server.go中grpc服务的编写!
代码如下:
grpc_server.go
package main
import (
"google.golang.org/grpc"
"google.golang.org/grpc/grpclog"
"grpc1/service"
"net"
)
func main() {
//获取grpc服务端
rpcServer := grpc.NewServer()
//服务端映射(注册)到结构体
service.RegisterProductServiceServer(rpcServer, service.ProductService)
// 建立tcp端口监听
listener, err := net.Listen("tcp", ":8002")
if err != nil {
grpclog.Fatal("启动监听出错", err)
}
//服务端监听tcp连接
err = rpcServer.Serve(listener)
if err != nil {
grpclog.Fatal("启动服务出错", err)
}
}
5、编写grpc客户端代码,进行测试
新建client目录,grpc_client.go文件,编写客户端代码,使用远程调用服务端的方法。
grpc_client.go
package main
import (
"google.golang.org/grpc"
"google.golang.org/grpc/grpclog"
"grpc1/service"
"net"
)
func main() {
//获取grpc服务端
rpcServer := grpc.NewServer()
//服务端映射(注册)到结构体,调用product_grpc.pb.go中的RegisterProductServiceServer方法
service.RegisterProductServiceServer(rpcServer, service.ProductService)
// 建立tcp端口监听
listener, err := net.Listen("tcp", ":8002")
if err != nil {
grpclog.Fatal("启动监听出错", err)
}
//服务端监听tcp连接
err = rpcServer.Serve(listener)
if err != nil {
grpclog.Fatal("启动服务出错", err)
}
}
运行客户端,运行服务端
启动服务端
启动客户端,如图所示,客户端成功调用的服务端方法,返回查询数据