GO语言 使用protobuf

1.什么是protobug,为什么要学它

protobuf是一种类似于json和xml的数据序列化格式

我们可能会存在这样的问题:不同语言之间真的没有办法互相传递数据吗?如果可以,那如果一个项目使用了多种语言有应该如何传递数据?

这个过程其实很简单,就是拆解与拼装的过程,假如我们有一个数据a,这个数据在另一个语言内没有直接对应的结构。我们就可以把它序列化即转为二进制传输。只需要发送方和接收方使用的是同一种数据序列化格式即可。protobuf就是其中之一。

我们为什么要使用protobuf呢?简单来说是因为它快,而且更适用于后端服务之间的交流。json我们通常用于前后端的交流,而后端服务之间的交流就是使用的protobuf。但是这并不是绝对的,json同样可以用于后端服务之间的交流。

2.配置protobuf的环境

下载地址:Releases · protocolbuffers/protobuf

下载好之后我们解压压缩包到指定的路径,这个路径自己设置即可我们这里假设路径是C:\protobuf

然后添加环境变量

bin 目录添加到系统 PATH 环境变量:

Win + R,输入 sysdm.cpl 打开系统属性

进入 高级 → 环境变量 → 系统变量 ,编辑 Path

添加新条目:C:\protobuf\bin

点击确定保存

最后运行:protoc --version查看版本,如果从输出版本就说明是安装好了

我们再安装GO语言的protobuf插件

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

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

查看是否安装成功

dir %GOPATH%\bin\protoc-gen*

3.编写一个proto文件

首先我们创建一个.proto文件,然后输入

复制代码
syntax = "proto3";  // 使用 proto3 语法

package example;    // 包名,防止命名冲突

option go_package = "github.com/grpc/"; // Go 包路径,它的设置关乎生成go文件后存放的路径

message Person {
    string name = 1;       // 字段编号必须从1开始,这是编号不是变量的值
    int32 age = 2;
}

4.生成go文件

然后在终端进入到该文件所在的目录输入命令:

protoc -I . test.proto --go_out=. --go-grpc_out=.

这时候我们会发现在该文件的目录下多了一个叫github.com的目录,它里面有一个grpc目录,这个目录存放的是我们最终生成的文件。然后我们根据这个路径导入这个go文件

这样我们就可以使用它了,根据我们proto文件的内容,它有一个叫Person的结构体可以让我们使用。

我们在main.go里面导入我们生成的文件(假设:github.com/grpc/test.pb.go)

我们使用 :test := &grpc.Person{Age: 10, Name: "xxx"}生成一个这样的结构体指针,到这里它其实和我们自己在go里面定义的结构体无差别,单最大的差别就是:test这个结构体指针可以使用proto.Marshal()序列化,既然可以序列化那也就可以反序列化

序列化代码:

复制代码
test := &grpc.Person{Age: 10, Name: "xxx"}
marshal, _ := proto.Marshal(test)
fmt.Println(marshal)

我们输出序列化的内容之后就会发现是一串编码(如:[10 3 120 120 120 16 10])这就是序列化后的结果。

反序列化代码:

复制代码
unmarshal := &grpc.Person{}
_ = proto.Unmarshal(marshal, unmarshal)
fmt.Println(unmarshal)

这里我们先创建一个空的结构体指针,用于存储我们后面的反序列化结果,最后输出了正常的结果:name:"xxx" age:10

这里我们还要讲一下生成.go文件存放的路径问题,我们上面讲解的方法虽然可行,但是多重目录看起来确实不美观。如果可以我们可以使用

首先设置option go_package = "./file;name" 分号前面是路径,后面是生成的.go文件所属的包

然后我们在使用命令生成的时候使用:protoc --go_out=. --go-grpc_out=. *.proto

这个命令会生成所有.proto文件的.go文件,如果需要单独生成某个文件则需要把 * 换成指定文件名

这个命令只会生效于当前目录的proto文件,子目录下的proto文件不会生效

|------|--------------------------------------------|----------------------------------------------|
| 命令 | protoc --go_out=. --go-grpc_out=. *.proto | protoc -I . *.proto --go_out=plugins=grpc:. |
| 版本 | 比较新 | 比较旧 |
| 是否推荐 | 推荐 | 不推荐 |

相关推荐
Asthenia041210 分钟前
什么是语法分析 - 编译原理基础
后端
Asthenia041223 分钟前
理解词法分析与LEX:编译器的守门人
后端
uhakadotcom24 分钟前
视频直播与视频点播:基础知识与应用场景
后端·面试·架构
Asthenia04121 小时前
Spring扩展点与工具类获取容器Bean-基于ApplicationContextAware实现非IOC容器中调用IOC的Bean
后端
bobz9652 小时前
ovs patch port 对比 veth pair
后端
Asthenia04122 小时前
Java受检异常与非受检异常分析
后端
uhakadotcom2 小时前
快速开始使用 n8n
后端·面试·github
JavaGuide2 小时前
公司来的新人用字符串存储日期,被组长怒怼了...
后端·mysql
bobz9652 小时前
qemu 网络使用基础
后端
Asthenia04123 小时前
面试攻略:如何应对 Spring 启动流程的层层追问
后端