一、安装 Protocol Buffers

1、打开下载地址:https://github.com/protocolbuffers/protobuf/releases

找到对应的版本和对应的安装程序

dotnet grpc 自动生成 grpc生成go代码_dotnet grpc 自动生成


dotnet grpc 自动生成 grpc生成go代码_dotnet grpc 自动生成_02


2、下载完成解压 放到电脑磁盘,然后添加环境变量

dotnet grpc 自动生成 grpc生成go代码_字段_03


dotnet grpc 自动生成 grpc生成go代码_dotnet grpc 自动生成_04


dotnet grpc 自动生成 grpc生成go代码_golang_05


检查配置是否成功:win+R cmd 回车输入:protoc

dotnet grpc 自动生成 grpc生成go代码_dotnet grpc 自动生成_06


二、安装grpc核心库

1、下载地址:go get google.golang.org/grpc

2、安装go代码生成器:

go install google.golang.org/protobuf/cmd/protoc-gen-go@latest

go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@latest

三、proto文件编写

// 指定 proto 的版本信息
syntax = "proto3";

// 指定生成的 go 文件存放位置及其包名
option go_package = ".;service";


// 定义枚举消息体
message HelloRequest{
  string requestName = 1;
}

message HelloResponse{
  string responseMsg = 1;
}

service SayHello{
  rpc SayHello(HelloRequest) returns (HelloResponse){}
}

1、切换到proto文件位置,打开编辑器终端输入命令:

protoc --go_out=. .\hello.proto 
protoc --go-grpc_out=. .\hello.proto

生成文件:

dotnet grpc 自动生成 grpc生成go代码_Server_07


四、proto文件详解

Sacred

Sacred

关注

1,message介绍

message:protobuf中定义一个消息类型是通过关键字message字段指定的。消息就算需要传输的数据格式的定义。message关键字类似于C++中的class,Java中的Class,go中的struct

例如:

dotnet grpc 自动生成 grpc生成go代码_Server_08

在消息中承载的数据分别对应于每一个字段。

其中每个字段都有一个名字和一种类型。

2,字段规则

required:消息体中必填字段,不设置会导致编解码异常。一般不填就认为是必填字段了。
optional:消息体中可选字段。生成的是对应的指针。
repeated:消息体中可重复字段,重复的值的顺序会被保留,在go中重复的会被定义为切片。

这里我们来定义一下

dotnet grpc 自动生成 grpc生成go代码_字段_09

然后我们生成一下

dotnet grpc 自动生成 grpc生成go代码_Server_10

看下文件

dotnet grpc 自动生成 grpc生成go代码_Server_11

这里就变成了一个切片

3,字段映射

dotnet grpc 自动生成 grpc生成go代码_golang_12


dotnet grpc 自动生成 grpc生成go代码_golang_13

4,默认值

protobuf3删除了protobuf2中用来设置默认值的default关键字,取而代之的是protobuf3为各类型定义的默认值,也就是约定的默认值,如下表:

dotnet grpc 自动生成 grpc生成go代码_字段_14

5,标识号

标识号:在消息体的定义中,每个字段都必须要有一个唯一的标识号,标识号是[0.2^29-1]范围内的一个整数。

dotnet grpc 自动生成 grpc生成go代码_golang_15

以Person为例,name=1,id=2,email=3,phones=4中的1-4就是标识号

6,定义多个消息类型

一个proto文件中可以定义多个消息类型

dotnet grpc 自动生成 grpc生成go代码_Server_16

7,嵌套消息

可以在其他消息类型中定义,使用消息类型,在下面的例子中,Person消息就定义在PersonInfo消息内

dotnet grpc 自动生成 grpc生成go代码_Server_17

如果你想在它的父消息类型的外部重用这个消息类型,你需要以PersonInfo.Person的形式来使用它,如:

dotnet grpc 自动生成 grpc生成go代码_Server_18

当然,你也可以将消息嵌套任意多层,如:

dotnet grpc 自动生成 grpc生成go代码_dotnet grpc 自动生成_19

8,定义服务

如果想要将消息类型用在RPC系统中,可以在.PROTO文件中定义一个RPC服务接口,protocolbuffer编译器会根据所选择的不同语言生成服务接口代码及存根。

dotnet grpc 自动生成 grpc生成go代码_dotnet grpc 自动生成_20

上述代表表示,定义了一个RPC服务,该方法接收SearchRequest返回SearchResponse

五、服务端编写
创建grpc Server 对象,你可以理解为Server端的抽象对象
将server(其包含需要被调用的服务端接口)注册到grpc Server的内部注册中心
创建监听Listen,监听tcp端口

package main

import (
	"context"
	"fmt"
	"google.golang.org/grpc"
	pb "grpc_study/hello-server/proto"
	"net"
)

type server struct {
	pb.UnimplementedSayHelloServer
}

func (s *server) SayHello(ctx context.Context, req *pb.HelloRequest) (*pb.HelloResponse, error) {
	return &pb.HelloResponse{ResponseMsg: "hello" + req.RequestName}, nil
}

func main() {
	//开启端口
	listen, _ := net.Listen("tcp", ":9090")

	//创建grpc服务
	grpcServer := grpc.NewServer()

	//在grpc服务端中去注册我们自己编写的服务
	pb.RegisterSayHelloServer(grpcServer, &server{})

	//启动服务
	err := grpcServer.Serve(listen)
	if err != nil {
		fmt.Println("failed to server %v", err)
		return
	}

}

六、编写客户端
创建与服务端的链接交互
创建server的客户端对象
发生rpc请求,等待同步响应。得到调用后返回结果
输出响应结果

package main

import (
	"context"
	"fmt"
	"google.golang.org/grpc"
	"google.golang.org/grpc/credentials/insecure"
	pb "grpc_study/hello-server/proto"
	"log"
)

func main() {
	//链接server端,此处禁用安全传输,没有加密和验证
	conn, err := grpc.Dial("127.0.0.1:9090", grpc.WithTransportCredentials(insecure.NewCredentials()))
	if err != nil {
		log.Fatalf("did not connect %v", err)
	}
	defer conn.Close()

	//建立连接
	client := pb.NewSayHelloClient(conn)
	//执行grpc调用
	resp, _ := client.SayHello(context.Background(), &pb.HelloRequest{RequestName: "xiaoming"})

	fmt.Println(resp.GetResponseMsg())
}