Golang高级编程:Go协议缓冲区教程

时间:2019-10-31 作者:golang

Golang高级编程:Go协议缓冲区教程

欢迎各位编码员!在本教程中,我们将研究如何在基于Go的应用程序中利用Protocol Buffers数据格式。我们将介绍数据格式是什么,以及为什么它是对更传统的数据格式(例如XML甚至JSON)的改进。在尝试更复杂的示例之前,我们将深入研究一个简单的示例以使我们起步并运行。

在本教程结束时,您应该对基础知识相当熟悉,随后您便可以开始构建自己的更高级的系统。

协议缓冲区数据格式
协议缓冲区本质上是一种数据格式,就其存储可通过多种不同语言进行序列化或反序列化的结构化数据的意义而言,很像JSON或XML。

这种格式的主要优点是,与XML甚至JSON之类的格式相比,它的地狱要小得多。这种格式最初是由Google开发的,Google是一家相当著名的公司,它的大小如此之大,以至于他们可以保存的每个字节都不同。

假设我们有一个人,我们想用3种不同的数据格式表示他们的数据:

Elliot
24
我们可以在JSON中用更小的尺寸表示这些数据:

{
“name”: “Elliot”,
“age”: 24
}
如果我们使用协议缓冲区中的数据格式来表示此相同的数据:

[10 6 69 108 108 105 111 116 16 24]
如果仔细看一下上面的有线编码输出,您可能会发现,从数组中的位置2开始,名称elliot被拼写为e= 69,l= 108,依此类推。接下来是我当前年龄24岁的字节表示。

编码格式还有很多不尽人意之处,如果您愿意,我仍在尝试更详细地学习这点,我建议您在此处查看Google自己的文档: Protocol Buffer Encoding。

现在,尽管在此规模上JSON和协议缓冲区表示的各自大小可能相似,但是当我们开始考虑数据大于您的标准“入门”示例的场景时,节省的费用开始增加。

一个简单的例子

& 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二进制文件对此进行编译:

$ protoc --go_out=. *.proto

 

我们终于有了一切准备,开始编写go代码。我们先定义一个新Person对象,然后将其编组为一个protobuf 对象。

为了让人们了解这是如何存储,调用fmt.Println(data)打印出存储我们的线编码格式的protobuf对象。

main.go

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文件,以及在为了这个工作:

$go run main.go test.pb.go
[10 6 69 108 108 105 111 116 16 24]
name:"Elliot" age:24

 

 

嵌套字段
好的,我们已经设法建立并运行了一个非常简单的示例,但是在现实世界中,我们很可能在消息格式内有多个嵌套字段,并且我们将修改一些值等。

让我们看一下如何开始使用嵌套字段。我们将继续使用Person消息类型,并添加一个嵌套字段,其中将包含社交媒体关注者。

我们可以将标准字段类型和自定义SocialFollowers 消息类型的Person组成如下:

main.go

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程序时,可以使用以下命令填充elliot 对象SocialFollowers:

main.go

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())

}

 

当我们最后一次运行它时,我们看到一切都按预期打印了:

$go run main.go test.pb.go
Elliot
24
1400
2500

 

结论
因此,在本教程中,我们很好地了解了如何在自己的基于Go的应用程序中以协议缓冲区数据格式启动和运行。

声明:本文内容由互联网用户自发贡献自行上传,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任。如果您发现有涉嫌版权的内容,欢迎发送邮件至:2100506673@qq.com 进行举报,并提供相关证据,工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。