13

gRPC in ASP.NET Core 3.x -- Protocol Buffer, Go语言的例子(上)

 4 years ago
source link: http://mp.weixin.qq.com/s?__biz=MzAwNTMxMzg1MA%3D%3D&%3Bmid=2654077578&%3Bidx=7&%3Bsn=ad5b86375535aea2ce055be8323873d0
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

前两篇文章半年前写的:

gRPC in ASP.NET Core 3.0 -- Protocol Buffer(1)

gRPC in ASP.NET Core 3.0 -- Protocol Buffer(2)

之前把protocol buffer的基础知识讲了一遍,今天使用Go语言做一些例子。

最终目的是要做一个ASP.NET Core 和 Go Web之间的gRPC通信实例。

建立Go项目

在GOPATH的src下面建立一个文件夹 protobuf-go,然后在里面执行命令

go mod init github.com/solenovex/protobuf-go

这个命令是用来初始化go module的。

命令执行后在该目录生成go.mod文件,其内容如下:

eiAnyey.png!web

其实直接执行go mod init 也行,默认会取当前文件夹的名字作为项目名。

如果你使用的是Goland,那么需要启用Go modules集成:

bUNrieu.jpg!web

然后我们需要安装Protocol buffer的 Go 支持库:

go get -u github.com/golang/protobuf/protoc-gen-go

安装好之后:

zeMfIbJ.png!web

下面会出现require github.com/…. 后边显示indirect,说明我们的代码还没有对其进行直接引用

建立main.go,代码如下:

fIFNju3.png!web

然后执行命令 go run main.go 如果输出 "hello world!" 就说明一切正常。

建立proto

在项目下建立src/first文件夹,在里面建立person.proto文件:

fInUZvV.png!web

下面需要通过这个proto文件,生成go的代码,命令行执行:

protoc --proto_path src/ --go_out=src/ src/first/person.proto

执行完之后,在src/first文件夹下会生成一个文件person.pb.go:

rYvqMfj.jpg!web

我们看一下这个文件里的PersonMessage 这个struct:

bAvi6zY.jpg!web

这里面前4个属性就是proto文件里面定义的那4个属性,每个属性后边都跟着一个字符串tags,它里面提供了一些反射需要的信息。

例如id属性后边这个:

它表示:

  • 针对protocol buffer转换,它的类型是varint,tag为1,opt应该是proto2里面遗留下来的东西不用去管,名子为id,协议是proto3.

  • 针对json序列化,它的名为id,omitempty大概可以理解为如果值为该类型的默认值,那么id这个key就会被忽略掉。

该文件里面的其余内容我就不介绍了,但是注意,这个文件不可以修改!

使用proto生成的代码

在main.go里面建立一个新的函数NewPersonMessage,然后main函数调用它:

AFBjiqJ.jpg!web

在NewPersonMessage函数里面,我们New了一个生成文件里面的PersonMessage这个struct,并把4个属性赋了值,最后把它赋给变量pm。

可以通过pm.xx属性来修改它的值,也可以通过pm.GetXx()来获取其属性的值。

执行go run main.go之后结果如下:

FbqUFfB.png!web

修改package名

proto生成的go文件的package名并不是很符合约定,有一种约定是proto生成的go文件的package名应该以诗上层目录名+pb:

MJr6faE.png!web

所以我可以修改proto文件,添加一个option:

vYfAziu.png!web

option go_package 的值就是 生成go文件的package名。

再次执行:

protoc --proto_path src/ --go_out=src/ src/first/person.proto

这次生成的go文件的package就是:

A3UrUzm.png!web

把数据写入到文件

下面把NewPersonMessage添加一个返回类型:

aqUbimJ.png!web

返回PersonMessage的指针。

然后在main函数里通过NewPersonMessage函数获取一个PersonMessage,然后再建立一个writeToFile函数,把数据写入到文件里:

ANVNjej.jpg!web

这里面writeToFile函数的第一个参数是文件名,第二个参数是proto.Message类型,它是一个接口,其代码如下:

I7BzmiQ.png!web

而person.proto生成的PersonMessage struct正好拥有这些方法,所以它就是实现了该接口,所以在main在调用writeToFile函数的时候,可以将PersonMessage传递进去。

writeToFile里面的代码很简单,就是把数据写入到制定的文件里,文件权限模式为0644。

然后执行 go run main.go 会生成person.bin文件:

JviuMju.png!web

它是个二进制文件,编辑器无法打开查看内容。

从文件读取数据

添加一个readFromFile函数,用来从文件读取数据:

ryUNZ3m.jpg!web

然后在main函数里面new一个PersonMessage的指针,它的各属性值都没填,把这个指针传入到readFromFile函数里面,在里面使用proto.Unmarshal方法把数据写入到该指针指向的struct里面。

最后在main函数里进行打印,其结果如下:


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK