Skip to main content
 首页 » 编程设计

Golang Protocol Buffer教程

2022年07月19日135lonelyxmas

Golang Protocol Buffer教程

本文介绍如何在Go应用中利用Protocol Buffer数据格式。主要包括什么是Protocol Buffer数据格式,其超越传统数据格式XML或JSON的优势是什么。

1. Protocol Buffer数据格式

Protocol Buffer,本质就是一种数据格式,和JSON或XML一样,不同的语言用于结构化数据序列化或反序列化。该数据格式的优势是较xml或json更小,源于Google。假如我们有一个对象,我们用三种数据结构进行表示:

<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] 

如果您仔细观察上面编码可能会看到,从数组位置2开始名字elliot被拼出来,e = 69, l = 108等等。后面是年龄的字节表示,24岁。

不过编码格式内容比我们看到的要多,下面会更详细地解释,如果您愿意可看其官方文档

现在这个示例数据,Json和 Protocol Buffer格式几乎没有太大差别,但当遇到数据量很大场景时,差别就体现出来了。

2. 简单示例

首先下载必要的依赖:

go get github.com/golang/protobuf 
go get github.com/golang/protobuf/proto 

下载完成后,确保能够在命令行中可以运行 protoc 命令。下面我们定义 protobuf 结构,这里定义上面用来对比不同数据格式之间差异的person 对象。

首先指定我们使用的语法格式,这里使用 proto3,然后指定存放的包名。最后定义对象,Peson类型的消息及其包括的字段 nameage

person.proto结构定义如下:

syntax="proto3"; 
 
package main; 
 
message Person { 
      string name = 1; 
      int32 age = 2; 
} 

然后在该文件的路径下运行下面命令:

protoc --go_out=. *.proto 

即在当前目录下 生成所有扩展名为 proto文件的 .pb.go 文件。
现在我们定义Person类型对象使用 protobuf格式进行序列化。代码如下;

 
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) 
  } 
 
  // 打印原始的protobuf序列化对象 
  fmt.Println(data) 
 
 
  // 反序列化进行验证 
  newElliot := &Person{} 
  err = proto.Unmarshal(data, newElliot) 
  if err != nil { 
    log.Fatal("unmarshaling error: ", err) 
  } 
 
  // 打印 `newElliot` 对象进行验证 
  fmt.Println(newElliot.GetAge()) 
  fmt.Println(newElliot.GetName()) 
 
} 

使用go run 命令运行,需要在main.go 后面传入 person.pb.go,命令如下:

go run main.go test.pb.go 

在ide环境中可以直接运行。输出结果如下:

[10 6 69 108 108 105 111 116 16 24] 
name:"Elliot" age:24 

3. 嵌套示例

我们已经完成了一个非常简单的示例,但现实中消息格式通常会遇到多个嵌套字段,下面增加嵌套类型字段。

我们仍然使用前面 Person 类型,仅增加社交网络的粉丝字段。SocialFollowers的消息类型如下:

syntax="proto3"; 
 
package main; 
 
message SocialFollowers { 
  int32 youtube = 1; 
  int32 twitter = 2; 
} 
 
message Person { 
  string name = 1; 
  int32 age = 2; 
  SocialFollowers socialFollowers = 3; 
} 

因为Person 类型已经被修改了,需要重新运行 protoc 命令:

protoc --go_out=. *.proto 

现在同时修改代码进行测试,填充 elliot 对象使用 SocialFollowers 类型对象:

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) 
  } 
 
  // 反序列化对象进行验证 
  newElliot := &Person{} 
  err = proto.Unmarshal(data, newElliot) 
  if err != nil { 
    log.Fatal("unmarshaling error: ", err) 
  } 
 
  // 输出 `newElliot` 对象属性进行验证 
  fmt.Println(newElliot.GetName()) 
  fmt.Println(newElliot.GetAge()) 
  fmt.Println(newElliot.SocialFollowers.GetTwitter()) 
  fmt.Println(newElliot.SocialFollowers.GetYoutube()) 
} 

运行程序输出结果:

Elliot 
24 
1400 
2500 

4. 总结

本文我们学习了Go应用中如何使用 protocol buffer 数据格式。


本文参考链接:https://blog.csdn.net/neweastsun/article/details/108326704
阅读延展