乘风原创程序

  • Golang Protocol Buffer案例详解
  • 2021/8/17 17:55:21
  • 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类型的消息及其包括的字段 name 和 age。

    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 数据格式。

    到此这篇关于golang protocol buffer案例详解的文章就介绍到这了,更多相关golang protocol buffer内容请搜索本教程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持本教程网!