Go 中 Protocol Buffer 教程
欢迎程序员们!在这个教程里面,我们将学习如何使用protocol Buffers数据格式在你的go应用里面. 我们将详细讲述这种数据格式,以及为什么这种数据格式优于传统的数据格式例如xml甚至JSON. 在我们写更多复杂的例子之前,我们将从一个简单的例子开始编写运行.
在这章教的最后,你会对protoco Buffe有一个基础的了解,并且你将可以顺利的写出你自己更好的系统.
视频教程
https://www.youtube.com/embed/NoDRq6Twkts?ecver=2
Protocol Buffer数据类型
Protocol buffers是基础的数据格式, 和JSON,XML非常的相似, 都是用于存储结构化的数据,都支持很多不同的语言使用并进行序列化和反序列化.
这种数据格式最大的优点就是它相比xml甚至JSON的大小要小很多. 这种格式是由Google开发的.Goggole是非常有名的公司,它的规模如此之大,他们做的每一件事情都产生深渊的影响.
假设有一个人, 我们想用三个独立的数据表示他:
<person>
<name>Elliot</name>
<age>24</age>
</person>
我们可以使用更小的数据格式JSON表示他:
{
"name": "Elliot",
"age": 24
}
如果我们使用protocol buffer数据格式表示如下:
[10 6 69 108 108 105 111 116 16 24]
如果你仔细观察上面一行的编码输出, 你可以看到从数组下标为二的位置开始,ellio
就拼出来了.e
=69,l
=108等. 后面的字节表示我现在24岁了.
但是这个编码内容比我们看到的要多的多. 我仍然在尝试研究更多信息.如果你愿意,我建议可以查看更多Google关于protocol Buffer编码的文档:Protocol Buffer Encoding
虽然JSON和Protocol Buffer的大小几乎相同.但是随着数据增大大于"入门"例子的数据,Json和protocol buffer使用的空间差距就变大了.
一个简单的例子
& go get github.com/golang/protobuf
$ go get github.com/golang/protobuf/proto
上面下载一些必须的包,用于运行简单的例子.
($) export PATH=$PATH:$GOPATH/bin
进行上面的设置之后,你就可以在终端使用protoc
这个命令了. 下面我们就可以定义protobuf的格式了,在这个例子里,我们将尝试使用相同的person
这个对象,我们用这个突出不同数据格式之间的区别.
首先我们要指出要使用的协议类型, 在这个例子里面我们使用proto3
. 然后我把它作为main
包的一部分.
最后我们定义我们想要的数据结构. 这个包含了Person
的消息结构,其中包含了name
和 age
两个字段.
syntax="proto3";
package main;
message Person {
string name = 1;
int32 age = 2;
}
然后我们使用protoc
命令编译这个文件.
And we can then compile this using the protoc binary:
最终我们准备好写我们GO代码的所有东西. 我们从定义一个Person
开始,并将这个对象编译成protobuf
对象.
为了了解它是如何存储的,我们使用fmt.Println(data)
打印存储protobuf
对象的编码数据.
package main
import (
"fmt"
"log"
"github.com/golang/protobuf/proto"
)
func main() {
elliot := &Person{
Name: "Elliot",
Age: 24,
}
data, err := proto.Marshal(elliot)
if err != nil {
log.Fatal("marshaling error: ", err)
}
// printing out our raw protobuf object
fmt.Println(data)
// let's go the other way and unmarshal
// our byte array into an object we can modify
// and use
newElliot := &Person{}
err = proto.Unmarshal(data, newElliot)
if err != nil {
log.Fatal("unmarshaling error: ", err)
}
// print out our `newElliot` object
// for good measure
fmt.Println(newElliot.GetAge())
fmt.Println(newElliot.GetName())
}
在运行之前,我们需要将`test.pb.go'编译通过以保证正常工作:
➜ src go run main.go test.pb.go
[10 6 69 108 108 105 111 116 16 24]
name:"Elliot" age:24
嵌套字段
好了,我们实现了一个非常简单的例子并运行了它,但是在实际中,我们经常遇到在messag的格式里面有嵌套的字段,并且可能会修改一些它们的值.
现在我们开始看看如何使用嵌套字段. 我们继续使用 Person
这个消息格式,我们将添加一个社交媒体的追随者的字段.
我们用标准的字段以及自定义的SocialFollowers
消息字段组成Person这个消息格式,像下面这样:
syntax="proto3";
package main;
message SocialFollowers {
int32 youtube = 1;
int32 twitter = 2;
}
message Person {
string name = 1;
int32 age = 2;
SocialFollowers socialFollowers = 3;
}
再一次,我们使用protoc
这个命令生成我们想要的东西.
($) protoc --go_out=. *.proto
然后我们再回到我们的Go程序,我们可以用SocialFollowers
补充我们的elliot
对象:
package main
import (
"fmt"
"log"
"github.com/golang/protobuf/proto"
)
func main() {
elliot := Person{
Name: "Elliot",
Age: 24,
SocialFollowers: &SocialFollowers{
Youtube: 2500,
Twitter: 1400,
},
}
data, err := proto.Marshal(&elliot)
if err != nil {
log.Fatal("marshaling error: ", err)
}
// let's go the other way and unmarshal
// our protocol buffer into an object we can modify
// and use
newElliot := &Person{}
err = proto.Unmarshal(data, newElliot)
if err != nil {
log.Fatal("unmarshaling error: ", err)
}
// print out our `newElliot` object
// for good measure
fmt.Println(newElliot.GetName())
fmt.Println(newElliot.GetAge())
fmt.Println(newElliot.SocialFollowers.GetTwitter())
fmt.Println(newElliot.SocialFollowers.GetYoutube())
}
我们来最后一次运行它,我们看到了所有我们希望输出的内容:
➜ src go run main.go test.pb.go
Elliot
24
1400
2500
总结
在这个教程里面, 我们了解了如何基于Go应用程序使用protocol buffer建立数据结构并运行,
希望这个教程对您有用。
via: https://tutorialedge.net/golang/go-protocol-buffer-tutorial/
作者:tutorialedge.net译者:amei校对:校对者ID