Protobuf的介绍

Posted Harris-H

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Protobuf的介绍相关的知识,希望对你有一定的参考价值。

Protobuf的介绍

1.定义

Protocol buffers 是语言中立、平台中立、可扩展的结构化数据序列化机制,就像 XML,但是它更小、更快、更简单。你只需定义一次数据的结构化方式,然后就可以使用特殊生成的源代码轻松地将结构化数据写入和读取各种数据流,支持各种语言。因为profobuf是二进制数据格式,需要编码和解码。数据本身不具有可读性。因此只能反序列化之后得到真正可读的数据。

2.使用方法

  • 定义了一种源文件,扩展名为 .proto,使用这种源文件,可以定义存储类的内容(消息类型)
  • protobuf有自己的编译器 protoc,可以将 .proto 编译成对应语言的文件,就可以进行使用了,对于Go,编译器为文件中每种消息类型生成一个.pb.go文件。

3.实例

假设,我们现在需要传输用户信息,其中有username和age两个字段,创建文件user.proto,文件内容如下:

// 指定的当前proto语法的版本,有2和3
syntax = "proto3";
// option go_package = "path;name"; path 表示生成的go文件的存放地址,会自动生成目录
// name 表示生成的go文件所属的包名
option go_package="../service";
// 指定生成出来的文件的package
package service;
 
message User 
  string username = 1;
  int32 age = 2;

运行protoc命令编译成go中间文件

# 编译user.proto之后输出到service文件夹
protoc --go_out=../service user.proto

在go中使用测试:

package main
 
import (
    "Grpc-Protobuf/service"
    "fmt"
    "google.golang.org/protobuf/proto"
)
 
func main() 
    user := &service.User
        Username: "zhangsan",
        Age:      20,
    
    //转换为protobuf
    marshal, err := proto.Marshal(user)
    if err != nil 
        panic(err)
    
    newUser := &service.User
    err = proto.Unmarshal(marshal, newUser)
    if err != nil 
        panic(err)
    
    fmt.Println(newUser.String())

结果

username:"zhangsan" age:20

4.相关定义

4.1 消息类型(message)

protobuf中定义一个消息类型是通过关键字message字段指定的,消息就是需要传输的数据格式的定义。message可以包含多种类型字段(field),每个字段声明以分号结尾。message经过protoc编译后会生成对应的class类,field则会生成对应的方法。

message关键字类似于C++中的class,Java中的class,go中的struct

例如:

message User 
  string username = 1;
  int32 age = 2;

在消息中承载的数据分别对应于每一个字段。

其中每个字段都有一个名字和一种类型 。

4.2 字段规则

  • required:消息体中必填字段,不设置会导致编解码异常,此关键字可以忽略,例如message user中的username和age字段都是忽略required的必填字段。
  • optional: 消息体中可选字段。
  • repeated: 消息体中可重复字段,重复的值的顺序会被保留,在go中重复字段会被定义为切片。
message User 
  string username = 1;
  int32 age = 2;
  optional string password = 3;  // 生成的是指针
  repeated string address = 4;   // 生产的是切片

4.3 字段映射

.proto TypeNotesC++ TypePython TypeGo Type
doubledoublefloatfloat64
floatfloatfloatfloat32
int32使用变长编码,对于负值的效率很低,如果你的域有 可能有负值,请使用sint64替代int32intint32
uint32使用变长编码uint32int/longuint32
uint64使用变长编码uint64int/longuint64
sint32使用变长编码,这些编码在负值时比int32高效的多int32intint32
sint64使用变长编码,有符号的整型值。编码时比通常的 int64高效。int64int/longint64
fixed32总是4个字节,如果数值总是比总是比228大的话,这 个类型会比uint32高效。uint32intuint32
fixed64总是8个字节,如果数值总是比总是比256大的话,这 个类型会比uint64高效。uint64int/longuint64
sfixed32总是4个字节int32intint32
sfixed32总是4个字节int32intint32
sfixed64总是8个字节int64int/longint64
boolboolboolbool
string一个字符串必须是UTF-8编码或者7-bit ASCII编码的文 本。stringstr/unicodestring
bytes可能包含任意顺序的字节数据。stringstr[]byte

5.参考文章

文章1

定义数组

以上是关于Protobuf的介绍的主要内容,如果未能解决你的问题,请参考以下文章

Protobuf的简单介绍使用和分析

protobuf介绍和语法

protobuf介绍和语法

protobuf介绍和语法

Protobuf语法介绍

消息序列化工具-protobuf介绍及安装使用技巧