开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第7天,点击查看活动详情
记录下 golang 集成 Grpc + protobuf 的完整流程和开发,这个过程中可谓是走遍了各种坑,如果有不懂的可以留言或私信我
文章结尾附源码地址~
安装 protobuf
// mac下载方式
brew install protobuf
// 检查版本号 我这里用的是 3.19.x
protoc --version
安装 go 的 protoc 插件
// proto 文件生成 go文件
go get -u github.com/golang/protobuf/protoc-gen-go
go get google.golang.org/protobuf
安装完成后会在 GOPATH/bin 加入到环境变量就可以了
测试 proto 生成 go 文件
创建个proto文件
syntax = "proto3";
//option go_package = "path;name";
import "google/api/annotations.proto";
option go_package = "./student-go";
enum ClassName {//枚举
class1 = 0; //标号 必须从 0开始
class2 = 1;
class3 = 2;
}
message ListStudentReq {//消息,对应于Go的结构体
string name = 1; //1:标号,唯一 即可(相当于数据库中的Id,不一定要从1 ,2的顺序依次排列。)
int32 age = 2; //必须指定整型的范围,如int32,int64
string address = 3;
ClassName cn = 4;
}
message StudentsRes {
string school = 2;
}
service StudentService {
rpc ListStudent (ListStudentReq) returns (StudentsRes) {
option (google.api.http) = {
post: "/api/v1/calculation/discount/prompt"
body: "*"
};
}
}
因为proto 文件中会涉及第三方的包,这里先下载下面的文件放到自己的目录下
下载这个protobuf.zip文件,放到自己的执行目录下,我这里放到了 /User/song/下,然后解压
然后进入到proto文件夹下 执行下面语句
protoc --version 版本为 libprotoc 3.17.x
protoc --proto_path=./ -I. -I /Users/song/protobuf --go_out=plugins=grpc:. student.proto
protoc --version 版本为 libprotoc 3.19.x
protoc --proto_path=./ -I. -I /Users/song/protobuf --go_out=. --go-grpc_out=. student.proto
发现会生成两个文件
- student.pb.go --go_out 命令生成
- student_grpc.pb.go --go-grpc_out 生成
坑: libprotoc 3.19.x
-
在grpc server实现结构体中匿名嵌入Unimplemented***Server结构体
-
使用protoc生成server代码时命令行加上关闭选项,
protoc --go-grpc_out=require_unimplemented_servers=false
完整应该是
protoc --proto_path=./ -I. -I /Users/zhangshenghao/go/protobuf --go_out=. --go-grpc_out=require_unimplemented_servers=false:. student.proto
或者
protoc --proto_path=./ -I. -I /Users/zhangshenghao/go/protobuf --go_out=plugins=grpc:. student.proto
具体的protoc 命令可以去了解一下
创建grpc服务
- 实现接口
我们实现下 pb.go 文件中的方法
type Student struct {
}
func (*Student) GetStudentById(context.Context, *student.StudentReq) (*student.StudentRes, error) {
s := &student.StudentRes{}
s.Id = 1
s.Name = "zhang"
return s, nil
}
- 创建服务端
package main
import (
"flag"
"fmt"
"google.golang.org/grpc"
"google.golang.org/grpc/reflection"
"grpc-server/controller"
"grpc-server/proto/student"
"log"
"net"
)
func main() {
flag.Parse()
lis, err := net.Listen("tcp", fmt.Sprintf(":%d", 7001))
if err != nil {
log.Fatalf("failed to listen: %v", err)
}
grpcServer := grpc.NewServer()
// 注册服务
student.RegisterStudentServiceServer(grpcServer, &controller.Student{})
// 允许反射
reflection.Register(grpcServer)
grpcServer.Serve(lis)
}
使用 postman 的 grpc 功能进行测试
- 点击 new
- grpc request
3.输入 host 和 ip,红框2处会自动刷新反射出你的服务列表,选择你要测试的服务,message 中输入你的参数,我这里为了测试没有放入参,点击 invoke 输出结果,到此就结束了