protobuf

protobuf

Protocol Buffer其实是google出品的一种轻量高效的结构化数据存储格式,性能比xml,json强大很多

protobuf经历了protobuf2和protobuf3,pb3比pb2简化了许多,目前主流的是pb3

1.png

protobuf的语法

要想使用 protobuf必须得先定义 proto文件。所以得先熟悉 protobuf的消息定义的相关语法。

定义一个消息类型

message TestRequest{
    string name =1;//name表示名称,name的编号是1,而不是赋值
    int32 shenggao =2;
    //repeated相当于切片
    repeated int32 tizhong =3;
}

PandaRequest消息格式有3个字段,在消息中承载的数据分别对应于每一个字段。其中每个字段都有一个名字和
一种类型。 文件的第一行指定了你正在使用proto3语法:如果你没有指定这个,编译器会使用proto2。这个指定
语法行必须是文件的非空非注释的第一个行。 在上面的例子中,所有字段都是标量类型:两个整型(shengao和tizhong),一个string类型(name)。 Repeated 关键字表示重复的那么在go语言中用切片进行代表 正如上述
文件格式,在消息定义中,每个字段都有唯一的一个标识符。至于后面的1,2,3其实只是一个顺序标记,按照规则写即可。

单文件多消息

在一个.proto文件中可以定义多个消息类型。在定义多个相关的消息的时候,这一点特别有用——例如,如果想定
义与SearchResponse消息类型对应的回复消息格式的话,你可以将它添加到相同的.proto文件中。

syntax = "proto3";
message PandaRequest {
string name = 1;
int32 shengao = 2;
int32 tizhong = 3;
}
message PandaResponse {
...
}

从.proto文件生成了什么?

当用protocolbuffer编译器来运行.proto文件时,编译器将生成所选择语言的代码,这些代码可以操作在.proto文件中定义的消息类型,包括获取、设置字段值,将消息序列化到一个输出流中,以及从一个输入流中解析消息。
对C++来说,编译器会为每个.proto文件生成一个.h文件和一个.cc文件,.proto文件中的每一个消息有一个对应的类。 对Python来说,有点不太一样——Python编译器为.proto文件中的每个消息类型生成一个含有静态描述符的
模块,,该模块与一个元类(metaclass)在运行时(runtime)被用来创建所需的Python数据访问类。 对go来
说,编译器会为每个消息类型生成了一个.pd.go文件。

标准数据类型

.proto Type Notes C++ Type Python Type Go Type
double double float float64
float float float float32
int32 使用变长编码,对于负值的效率很低,如果你的域有 可能有负值,请使用sint64替代 int32 int int32
uint32 使用变长编码 uint32 int/long uint32
uint64 使用变长编码 uint64 int/long uint64
sint32 使用变长编码,这些编码在负值时比int32高效的多 int32 int int32
sint64 使用变长编码,有符号的整型值。编码时比通常的 int64高效。 int64 int/long int64
fixed32 总是4个字节,如果数值总是比总是比228大的话,这 个类型会比uint32高效。 uint32 int uint32
fixed64 总是8个字节,如果数值总是比总是比256大的话,这 个类型会比uint64高效。 uint64 int/long uint64
sfixed32 总是4个字节 int32 int int32
sfixed64 总是8个字节 int64 int/long i int64
bool bool bool bool
string 一个字符串必须是UTF-8编码或者7-bit ASCII编码的文 本。 string str/unicode string
bytes 可能包含任意顺序的字节数据。 string str []byte

默认值

当一个消息被解析的时候,如果被编码的信息不包含一个特定的元素,被解析的对象锁对应的域被设置位一个默认值,对于不同类型指定如下:对于strings,默认是一个空string 对于bytes,默认是一个空的bytes 对于bools,默认是false 对于数值类型,默认是0

使用其他消息类型

你可以将其他消息类型用作字段类型。例如,假设在每一个PersonInfo消息中包含Person消息,此时可以在相同的.proto文件中定义一个Result消息类型,然后在PersonInfo消息中指定一个Person类型的字段

message PersonInfo {
repeated Person info = 1;
}
message Person {
string name = 1;
int32 shengao = 2;
repeated int32 tizhong = 3;
}

嵌套类型

你可以在其他消息类型中定义、使用消息类型,在下面的例子中,Person消息就定义在PersonInfo消息内,如:

message PersonInfo {
message Person {
string name = 1;
int32 shengao = 2;
repeated int32 tizhong = 3;
}
repeated Person info = 1;
}

如果你想在它的父消息类型的外部重用这个消息类型,你需要以PersonInfo.Person的形式使用它,如:

message PersonMessage {
PersonInfo.Person info = 1;
}

当然,你也可以将消息嵌套任意多层,如:

message Grandpa { // Level 0
message Father { // Level 1
    message son { // Level 2
    string name = 1;
    int32 age = 2;
  }
}
    message Uncle { // Level 1
    message Son { // Level 2
    string name = 1;
    int32 age = 2;
  }
 }
}

定义服务(Service)

如果想要将消息类型用在RPC(远程方法调用)系统中,可以在.proto文件中定义一个RPC服务接口,protocol buffer编译器将会根据所选择的不同语言生成服务接口代码及存根。如,想要定义一个RPC服务并具有一个方法,该方法能够接收SearchRequest并返回一个SearchResponse,此时可以在.proto文件中进行如下定义:

service SearchService {
//rpc 服务的函数名 (传入参数)返回(返回参数)
rpc Search (SearchRequest) returns (SearchResponse);
}

生成访问类(了解)

常用的是下一个标题的指令

可以通过定义好的.proto文件来生成Java,Python,C++, Ruby, JavaNano, Objective-C,或者C# 代码,需要基
于.proto文件运行protocol buffer编译器protoc。如果你没有安装编译器,下载安装包并遵照README安装。对于
Go,你还需要安装一个特殊的代码生成器插件。你可以通过GitHub上的protobuf库找到安装过程
通过如下方式调用protocol编译器:

protoc --proto_path=IMPORT_PATH --cpp_out=DST_DIR --python_out=DST_DIR --
go_out=DST_DIR path/to/file.proto

IMPORT_PATH声明了一个.proto文件所在的解析import具体目录。如果忽略该值,则使用当前目录。如果有多个
目录则可以多次调用--proto_path,它们将会顺序的被访问并执行导入。-I=IMPORT_PATH是--proto_path的简化形式。

当然也可以提供一个或多个输出路径: --cpp_out 在目标目录DST_DIR中产生C++代码,可以在C++代码生成参考中查看更多。 --python_out 在目标目录 DST_DIR 中产生Python代码,可以在Python代码生成参考中查看更多。--go_out 在目标目录 DST_DIR中产生Go代码,可以在GO代码生成参考中查看更多。 作为一个方便的拓展,如果DST_DIR以.zip或者.jar结尾,编译器会将输出写到一个ZIP格式文件或者符合JAR标准的.jar文件中。注意如果输出已经存在则会被覆盖,编译器还没有智能到可以追加文件。-你必须提议一个或多个.proto文件作为输入,多个.proto文件可以只指定一次。虽然文件路径是相对于当前目录的,每个文件必须位于其IMPORT_PATH下,以便每个文件可以确定其规范的名称。

基本案例

syntax ="proto3";

package one;

message TestRequest{
    string name =1;
    int32 shenggao =2;
    //repeated相当于切片
    repeated int32 tizhong =3;

}


message TestResponse{
    int32 err =1;
    string ermessage =2;

}

指令:protoc --go_out=./ *.proto 会生成一个go文件,在同级目录下。前提是进入对应的有proto文件的目录,一般是项目目录下的某个文件夹,可以一个目录下多个proto文件。

protobuf做数据格式转换

package main

import (
    "proto1/one"
    "fmt"
    "github.com/golang/protobuf/proto"
)

func main() {
    info:=&one.TestRequest{
        Name:"zq",
        Tizhong:[]int32{120,150},
        Shenggao:180,
    }
    fmt.Println(info) //name:"zq" shenggao:180 tizhong:120 tizhong:150
    //编码
    bytes, err := proto.Marshal(info)
    if err!=nil{
        fmt.Println("编码失败")
    }
    fmt.Println(bytes) //[10 2 122 113 16 180 1 26 3 120 150 1]

    newinfo:=&one.TestRequest{}

    //解码
    err= proto.Unmarshal(bytes, newinfo)
    if err!=nil{
        fmt.Println("解码失败")
    }
    fmt.Println(newinfo) //name:"zq" shenggao:180 tizhong:120 tizhong:150

    //分别获取属性值
    fmt.Println(newinfo.Shenggao,newinfo.Tizhong,newinfo.Name)
}
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 211,884评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,347评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,435评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,509评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,611评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,837评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,987评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,730评论 0 267
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,194评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,525评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,664评论 1 340
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,334评论 4 330
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,944评论 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,764评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,997评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,389评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,554评论 2 349

推荐阅读更多精彩内容