Go中的gRPC入门教程详解
来到golang学习网的大家,相信都是编程学习爱好者,希望在这里学习Golang相关编程知识。下面本篇文章就来带大家聊聊《Go中的gRPC入门教程详解》,介绍一下gRPC、入门,希望对大家的知识积累有所帮助,助力实战开发!
Go GRPC 入门
1,安装包
grpc
golang-grpc 包提供了 gRPC 相关的代码库,通过这个库我们可以创建 gRPC 服务或客户端,首先需要安装他。
go get -u google.golang.org/grpc
协议插件
要玩 gRPC,自然离不开 proto 文件,需要安装两个包,用于支持 protobuf 文件的处理。
go get -u github.com/golang/protobuf go get -u github.com/golang/protobuf/protoc-gen-go
注:GOPATH/bin 下有个 protoc-gen-go.exe 文件,然而这个只是 protoc 的插件,他本身不是 protoc 工具。。。
Protocol Buffers
Protocol Buffers 是一个与编程语言无关、与平台无关的可拓展机制,用于序列化结构数据,是一种数据交换格式,gRPC 使用 protoc 作为协议处理工具。
学习 Go 的 gRPC 时,有个坑,很多文章里面都没有说到要安装这个,执行命令提示不存在 protoc 命令。
首先到 https://github.com/protocolbuffers/protobuf/releases 下载 相应的包,例如笔者下载的是 protoc-3.15.6-win64.zip。
解压后,复制里面的 bin\protoc.exe 文件,复制到 GOPATH\bin 命令,跟 protoc-gen-go.exe 放一起。
测试
以上都妥当后,我们在一个新的目录,创建一个 test.proto 文件,其内容示例如下如下:
注:protoc-3.15.6-win64\include\google\protobuf 目录也有很多示例。
syntax = "proto3";
// 包名
package test;
// 指定输出 go 语言的源码到哪个目录以及文件名称
// 最终在 test.proto 目录生成 test.pb.go
// 也可以只填写 "./"
option go_package = "./;test";
// 如果要输出其它语言的话
// option csharp_package="MyTest";
service Tester{
rpc MyTest(Request) returns (Response){}
}
// 函数参数
message Request{
string jsonStr = 1;
}
// 函数返回值
message Response{
string backJson = 1;
}
然后在 proto 所在目录,执行命令将 proto 转换为相应的编程语言文件。
protoc --go_out=plugins=grpc:. *.proto
会发现在当前目录输出了 test.pb.go 文件。
2,gRPC 服务端
创建一个 go 程序,把 test.pb.go 复制放到在 main.go 目录,在 main.go 引入 grpc:
import (
"context"
"fmt"
"google.golang.org/grpc"
// test.pb.go 默认包名是 package 为 main,不需要在这里引入
"google.golang.org/grpc/reflection"
"log"
"net"
)
在 test.pb.go 中,生成了两个个 Tester 的接口,我们来看一下这两个接口的定义:
type TesterServer interface {
MyTest(context.Context, *Request) (*Response, error)
}
type TesterClient interface {
MyTest(ctx context.Context, in *Request, opts ...grpc.CallOption) (*Response, error)
}
要实现 proto 中的服务,则需要我们实现 TesterServer 接口,要编写 客户端,则需要实现 TesterClient 。
这里我们先实现 Server。
// 用于实现 Tester 服务
type MyGrpcServer struct{}
func (myserver *MyGrpcServer) MyTest(context context.Context, request *Request) (*Response, error) {
fmt.Println("收到一个 grpc 请求,请求参数:", request)
response := Response{BackJson: `{"Code":666}`}
return &response, nil
}
接着我们创建 gRPC 服务。
func main() {
// 创建 Tcp 连接
listener, err := net.Listen("tcp", ":8028")
if err != nil {
log.Fatalf("监听失败: %v", err)
}
// 创建gRPC服务
grpcServer := grpc.NewServer()
// Tester 注册服务实现者
// 此函数在 test.pb.go 中,自动生成
RegisterTesterServer(grpcServer, &MyGrpcServer{})
// 在 gRPC 服务上注册反射服务
// func Register(s *grpc.Server)
reflection.Register(grpcServer)
err = grpcServer.Serve(listener)
if err != nil {
log.Fatalf("failed to serve: %v", err)
}
}
3,gRPC 客户端
创建一个新的 go 项目,把 test.pb.go 复制放到 main.go 同级目录,main.go 的代码:
package main
import (
"bufio"
"context"
"google.golang.org/grpc"
"log"
"os"
)
func main() {
conn, err := grpc.Dial("127.0.0.1:8028", grpc.WithInsecure())
if err != nil {
log.Fatal("连接 gPRC 服务失败,", err)
}
defer conn.Close()
// 创建 gRPC 客户端
grpcClient := NewTesterClient(conn)
// 创建请求参数
request := Request{
JsonStr: `{"Code":666}`,
}
reader := bufio.NewReader(os.Stdin)
for {
// 发送请求,调用 MyTest 接口
response, err := grpcClient.MyTest(context.Background(), &request)
if err != nil {
log.Fatal("发送请求失败,原因是:", err)
}
log.Println(response)
reader.ReadLine()
}
}
4,编译运行
由于创建的时候,test.pb.go 使用的包名是 main,所以在编译时,需要把多个 go 文件一起编译:
go build .\main.go .\test.pb.go
然后分别启动 server 和 client,在 client 每按下一次回车键,便发送一次 gRPC 消息。

到这里,我们学习了一个完整的 gRPC 从创建协议到创建服务和客户端的过程,下面将接着学习一些相关的知识,了解一些细节。
5,其它
proto.Marshal 可以对请求的参数进行序列化,如:
// 创建请求参数
request := Request{
JsonStr: `{"Code":666}`,
}
out,err:= proto.Marshal(&request)
if err != nil {
log.Fatalln("Failed to encode address book:", err)
}
if err := ioutil.WriteFile("E:/log.txt", out, 0644); err != nil {
log.Fatalln("Failed to write address book:", err)
}
而 proto.Unmarshal 则可以反序列化。
我们还可以自定义如何序列化反序列化消息,代码示例:
b, err := MarshalOptions{Deterministic: true}.Marshal(m)
GRPC
Protobuf buffer
Protobuf buffer 是一种数据格式,而 Protobuf 是 gRPC 协议,这里需要区分一下。
protobuf buffer 是 Google 用于序列化结构话数据的开源机制,要定义一个 protobuf buffer,需要使用 message 定义。
message Person {
string name = 1;
int32 id = 2;
bool has_ponycopter = 3;
}
开源看到,每个字段都有一个 数字, = 1 这个不是赋值,而是编号。一个 message 中,每个字段都有唯一的编号,这些数字用于标识二进制格式的字段(数据传输时会被压缩等),当编号范围是 1-15 时,存储编号需要一个字节,也就是说 message 中的字段尽量不超过 15 个,1-15 编号用来定义频繁出现的消息元素。当然,也可以使用16-2047 之间的数字作为编号,此时存储编号需要两个字节。
详细的说可以参考官方文档:
https://developers.google.com/protocol-buffers/docs/overview
字段类型
字段类型就不详细列表了,读者可以参考官方文档,这里列一下常用的数据类型:
double、float、int32、int64、bool、string、bytes、枚举。
由于 gRPC 需要考虑兼容 C 语言、C#、Java、Go 语言等,所以 gRPC 中的类型不等同于编程语言中的相关类型。这些类型都是 gRPC 中定义的,并且如果要转换为编程语言中的类型,需要一些转换机制,而这有时会十分麻烦。
字段规则
每个字段都可以指定一个规则,在定义字段类型的开头使用规则标识。
有以下三种规则:
required:格式正确的消息必须恰好具有此字段之一,即必填字段。optional:格式正确的消息可以包含零个或一个此字段(但不能超过一个,即值是可选的。repeated:在格式正确的消息中,此字段可以重复任意次(包括零次),重复值的顺序将保留,表示该字段可以包含0~N个元素。
由于历史原因,repeated标量数字类型的字段编码效率不高。新代码应使用特殊选项[packed=true]来获得更有效的编码。例如:
repeated int32 samples = 4 [packed=true];
在可选字段中 optional 中,我们可以为其设置一个默认值,当传递消息时如果没有填写此字段,则使用其默认值:
optional int32 result_per_page = 3 [default = 10];
Protobuf
接下来将介绍 gRPC 的协议格式(protobuf),下面是官方文档的一个示例:
syntax = "proto3"; package tutorial; import "google/protobuf/timestamp.proto";
syntax 指明协议的版本;
package 指明该 .proto 的名称;
import 关键字可以在当前 .proto 中引入其它 .proto 文件,gRPC 基本数据类型中不包含时间格式,可以引入 timestamp.proto。
不同编程语言引入包/库的方式是不同的,C++ 和 C# 都是使用命名空间区分代码位置;Java 以目录、公共类严格区别包名;go 则是以一个 .go 文件任意设置 package 名称。
前面提到了 protoc,可以将协议文件转为为具体的代码。
为了兼容各种编程语言,我们协议设置 _package,这样可以支持生成不同语言代码时设置包/库名称。
例如 :
option go_package = "Test"; // ...
option csharp_package = "MyGrpc.Protos"; // 生成命名空间 namespace MyGrpc.Protos{}
option java_paclage = "MyJava.Protos"; // ...
gRPC 四种服务方法
protobuf 中除了可以定义 message,也可以定义流式接口。
gRPC使您可以定义四种服务方法:
一元 RPC,客户端向服务器发送单个请求并获得单个响应,就像普通的函数调用一样。前面我们提到的都是一元 gRPC。
rpc SayHello(HelloRequest) returns (HelloResponse);
服务器流式RPC,客户端在其中向服务器发送请求,并获取流以读取回一系列消息。客户端从返回的流中读取,直到没有更多消息为止。gRPC保证在单个RPC调用中对消息进行排序。
客户端 -> 服务端 -> 返回流 -> 客户端 -> 接收流
rpc LotsOfReplies(HelloRequest) returns (stream HelloResponse);
客户端流式RPC,客户端在其中编写消息序列,然后再次使用提供的流将其发送到服务器。客户端写完消息后,它将等待服务器读取消息并返回其响应。gRPC再次保证了在单个RPC调用中的消息顺序。
客户端 -> 发送流 -> 服务端 -> 接收流 ->
rpc LotsOfGreetings(stream HelloRequest) returns (HelloResponse);
双向流式RPC,双方都使用读写流发送一系列消息。这两个流独立运行,因此客户端和服务器可以按照自己喜欢的顺序进行读写:例如,服务器可以在写响应之前等待接收所有客户端消息,或者可以先读取消息再写入消息,或读写的其他组合。每个流中的消息顺序都会保留。
rpc BidiHello(stream HelloRequest) returns (stream HelloResponse);
编译 proto
前面我们用 protoc 来编译 .proto 文件为 go 语言,为了支持编译为 go,需要安装 protoc-gen-go 插件,C# 可以安装 protoc-gen-zsharp 插件。
需要注意的是,转换 .proto 为编程语言,不一定要安装 protoc。
例如 C# 只需要把 .proto 文件放到项目中,通过包管理器安装一个库,就会自动转换为相应的代码。
回归正题,聊一下 protoc 编译 .proto 文件的命令。
protoc 常用的参数如下:
--proto_path=. #指定proto文件的路径,填写 . 表示就在当前目录下
--go_out=. #表示编译后的文件存放路径;如果编译的是 csharp,则 --csharp_out
--go_opt={xxx.proto}={xxx.proto的路径}
# 示例:--go_opt=Mprotos/bar.proto=example.com/project/protos/foo
最简单的编译命令:
protoc --go_out=. *.proto
--{xxx}_out 指令是必须的,因为要输出具体的编程语言代码。
这个输出文件的路径是执行命令的路径,如果我们不在 .proto 文件目录下执行命令,则输出的代码便不是相同位置了。为了解决这个问题,我们可以使用:
--go_opt=paths=source_relative
这样在别的地方执行命令,生成的代码会跟 .proto 文件放在相同的位置。
以上就是本文的全部内容了,是否有顺利帮助你解决问题?若是能给你带来学习上的帮助,请大家多多支持golang学习网!更多关于Golang的相关知识,也可关注golang学习网公众号。
Go语言中定时任务库Cron使用方法介绍
- 上一篇
- Go语言中定时任务库Cron使用方法介绍
- 下一篇
- Golang库插件注册加载机制的问题
-
- Golang · Go教程 | 2小时前 | 格式化输出 printf fmt库 格式化动词 Stringer接口
- Golangfmt库用法与格式化技巧解析
- 140浏览 收藏
-
- Golang · Go教程 | 2小时前 |
- Golang配置Protobuf安装教程
- 147浏览 收藏
-
- Golang · Go教程 | 2小时前 |
- Golang中介者模式实现与通信解耦技巧
- 378浏览 收藏
-
- Golang · Go教程 | 2小时前 |
- Golang多协程通信技巧分享
- 255浏览 收藏
-
- Golang · Go教程 | 2小时前 |
- Golang如何判断变量类型?
- 393浏览 收藏
-
- Golang · Go教程 | 2小时前 |
- Golang云原生微服务实战教程
- 310浏览 收藏
-
- Golang · Go教程 | 3小时前 |
- Golang迭代器与懒加载结合应用
- 110浏览 收藏
-
- Golang · Go教程 | 3小时前 | 性能优化 并发安全 Golangslicemap 预设容量 指针拷贝
- Golangslicemap优化技巧分享
- 412浏览 收藏
-
- Golang · Go教程 | 3小时前 |
- Golang代理模式与访问控制实现解析
- 423浏览 收藏
-
- Golang · Go教程 | 4小时前 |
- Golang事件管理模块实现教程
- 274浏览 收藏
-
- 前端进阶之JavaScript设计模式
- 设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
- 543次学习
-
- GO语言核心编程课程
- 本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
- 516次学习
-
- 简单聊聊mysql8与网络通信
- 如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
- 500次学习
-
- JavaScript正则表达式基础与实战
- 在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
- 487次学习
-
- 从零制作响应式网站—Grid布局
- 本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
- 485次学习
-
- ChatExcel酷表
- ChatExcel酷表是由北京大学团队打造的Excel聊天机器人,用自然语言操控表格,简化数据处理,告别繁琐操作,提升工作效率!适用于学生、上班族及政府人员。
- 3163次使用
-
- Any绘本
- 探索Any绘本(anypicturebook.com/zh),一款开源免费的AI绘本创作工具,基于Google Gemini与Flux AI模型,让您轻松创作个性化绘本。适用于家庭、教育、创作等多种场景,零门槛,高自由度,技术透明,本地可控。
- 3375次使用
-
- 可赞AI
- 可赞AI,AI驱动的办公可视化智能工具,助您轻松实现文本与可视化元素高效转化。无论是智能文档生成、多格式文本解析,还是一键生成专业图表、脑图、知识卡片,可赞AI都能让信息处理更清晰高效。覆盖数据汇报、会议纪要、内容营销等全场景,大幅提升办公效率,降低专业门槛,是您提升工作效率的得力助手。
- 3403次使用
-
- 星月写作
- 星月写作是国内首款聚焦中文网络小说创作的AI辅助工具,解决网文作者从构思到变现的全流程痛点。AI扫榜、专属模板、全链路适配,助力新人快速上手,资深作者效率倍增。
- 4506次使用
-
- MagicLight
- MagicLight.ai是全球首款叙事驱动型AI动画视频创作平台,专注于解决从故事想法到完整动画的全流程痛点。它通过自研AI模型,保障角色、风格、场景高度一致性,让零动画经验者也能高效产出专业级叙事内容。广泛适用于独立创作者、动画工作室、教育机构及企业营销,助您轻松实现创意落地与商业化。
- 3784次使用
-
- 基于微服务框架go-micro开发gRPC应用程序
- 2023-01-01 282浏览
-
- Golang gRPC HTTP协议转换示例
- 2022-12-24 213浏览
-
- GoGrpcGateway兼容HTTP协议文档自动生成网关
- 2022-12-28 135浏览
-
- Go gRPC进阶教程gRPC转换HTTP
- 2022-12-30 143浏览
-
- Go gRPC服务proto数据验证进阶教程
- 2023-01-09 360浏览

