Google Protobuf 简介与使用

1. 简介

Protocol Buffers是一种序列化数据结构的方法。对于通过导线或存储数据进行通信的程序开发上是很有用的。这个方法包含一个接口描述语言,描述一些数据结构,并且提供程序工具根据这些描述产生代码,用于将这些数据结构产生或解析数据流。

首先,protobuf是一个**开源 项 目(官方站点在“这里 ”),而且是后台很硬的开源项目。网上现有的大部分(至少80%)开源项目,要么是某人单干、要么是几个闲杂人等合伙搞。而protobuf则不然,它是 鼎鼎大名的Google公司开发出来,并且在Google内部久经考验的一个东东。由此可见,它的作者绝非一般闲杂人等可比。  那这个听起来牛X的东东到底有啥用处捏?简单地说,这个东东干的事儿其实和XML **差不多,也就是把某种数据结构的信息,以某种格式保存起来。主要用于数据存储、传输协议格式等场合。有同学可能心理犯嘀咕了:放着好好的XML不用,干嘛重新发明轮子啊?!先别急,后面俺自然会有说道。  话说到了去年(大约是08年7月),Google突然大发慈悲,把这个好东西贡献给了开源社区。这下,像俺这种喜欢捡现成的家伙可就有福啦!貌似喜欢 捡现成的家伙还蛮多滴,再加上 Google的号召力,开源后不到一年,protobuf的人气就已经很旺了。所以俺为了与时俱进,就单独开个帖子来忽悠一把。引用来自这里

ProBuffer 分为两个版本

  • pro2
  • pro3

2. 安装

请戳这里

3. 数据类型

类型 C++类型 Java类型
double double double
float float float
int32 int32 int
int64 int64 long

....

4. 使用

4.1 先瞅瞅是什么样子的
message Person { 
    required string name = 1; //的姓名
    required int32 id = 2; //唯一id
    optional string email = 3;//电子邮箱
}

message:表示一个消息定义。
required:表示这个参数是必选的,如果没有值会全部为空
optional:表示这个参数是可选,没有好像没什么影响,值为null
repeated:这个会生成数组。
//:表示注释
每个参数后面都会跟上一个tag,从1开始,每个tag从115暂用1个字节,162047占用2个字节。
所以我们使用的时候应该让经常出现的字段使用1~15这些tag,最小的tag数值是1,最大的数值是 2^29 - 1

通过命令可以生成对应的model
  • objc_out 表示的是输出Object-C文件
  • java_out 输出java文件
    ....
protoc --plugin=/usr/local/bin/protoc-gen-objc a.proto --objc_out=./

这是一个最基本的消息体,可以通过命令生成对应语言的model

IOS 需要安装类库,让生成的model序列化成二进制

使用cocoapod

pod 'Protobuf', '~> 3.1.0'
```
######4.2 定义一个带数组参数的消息体

```
message People{
 repeated string name = 1;
}
```
从消息体来看这个name 这个参数是`数组`,其中的内容类型是`string`,要注意的是 `repeated`是不能用 `required`和`optional`修饰的。
如果数组里面装的事基本类型就要添加`[packed=true]`
```
message People{
 repeated int32 repeated_number = 4 [packed=true];
}
```

######4.3 保留区域(Reserved Fields)

保留字段,编程过程中某些功能没有想好,可以先把该tag 进行保留,以备以后使用。
```
message Foo {
  reserved 2, 15, 9 to 11;
  reserved "foo", "bar";
}
```

######4.4 设置默认值

```
optional int32 result_per_page = 3 [default = 10];
```

###### ~~4.5 枚举类型(Enumerations)~~

```
message SearchRequest {
  required string query = 1;
  optional int32 page_number = 2;
  optional int32 result_per_page = 3 [default = 10];
  enum Corpus {
    UNIVERSAL = 0;
    WEB = 1;
    IMAGES = 2;
    LOCAL = 3;
    NEWS = 4;
    PRODUCTS = 5;
    VIDEO = 6;
  }
  optional Corpus corpus = 4 [default = UNIVERSAL];
}
```

用关键字**` enum `**定义一个枚举

######4.6 使用别的message类型

```
message SearchResponse {
  repeated Result result = 1;
}

message Result {
  required string url = 1;
  optional string title = 2;
  repeated string snippets = 3;
}
```

######4.7 导入

当需要使用导入其他的消息的时候可以使用下面的方法导入

```
import "myproject/other_protos.proto";
```

当然也可以导入`proto3`文件,但是`proto2`的枚举类型不能用在`proto3`的语法里面。

######4.8 message 的嵌套

有别于 4.6
```
message SearchResponse {
  message Result {
    required string url = 1;
    optional string title = 2;
    repeated string snippets = 3;
  }
  repeated Result result = 1;
}
```
如果想使用这用嵌套类型在去定义别的message可以这样使用`Parent.Type`
例如:
```
message SomeOtherMessage {
  optional SearchResponse.Result result = 1;
}
```

可以各种深度嵌套

```
message Outer {                  // Level 0
  message MiddleAA {  // Level 1
    message Inner {   // Level 2
      required int64 ival = 1;
      optional bool  booly = 2;
    }
  }
  message MiddleBB {  // Level 1
    message Inner {   // Level 2
      required int32 ival = 1;
      optional bool  booly = 2;
    }
  }
}
```
***
#####下面来说说比较实用的功能#####
***

######~~4.8 拓展(Extensions)~~

Extensions可以让程序不经过大的改动就可以增加新的功能。
```
message Foo {
  // ...
  extensions 100 to 199;
}
```
以上声明了一个叫做Foo的message 在改消息的Extensions部分声明了它的tag从100到199 这些Extensions 的tag可以在以后的扩展中实用,让我们看看Extensions 的使用
```
extend Foo {
  optional int32 bar = 126;
}
```
以上说明Foo 现在有了一个optional int32类型的bar。
但是如果要使用Extensions部分的内容就有点不一样了。(***这是C++的风格***)
```
Foo foo;
foo.SetExtension(bar, 15);
```
在生成的class 中有一下方法来操作Extensions
```
HasExtension(),
ClearExtension(),
GetExtension(),
MutableExtension(),
AddExtension(),
```

######4.8 使用one of

先看看定义

```
message SampleMessage {  
  oneof test_oneof {    
         string name = 4;    
         SubMessage sub_message = 9;  
}}
```

可以在one of 上加任何类型,但是不能加`required `,`optional`,`repeated` 这些关键字

让我们看看one of 的使用

```
SampleMessage message;
message.set_name("name");
CHECK(message.has_name());
message.mutable_sub_message();   // Will clear name field.CHECK(!message.has_name());
```

上面的`SampleMessage` 定义了一个message,如果向`name`赋值,那么name 现在的值就是`‘name’`,但是如果再向`sub_message `赋值,那么name 这个域将会为空,现在我们应该明白了**`one of`**的作用了吧.

#5. Map

首先看看map 的声明
```
map<key_type, value_type> map_field = N;
```
以下几点应当特别注意
- Extensions 不支持map
- map 不能设置为`repeated`,`optional`,`required `

如果map不支持`repeated` 怎么办,咱们有解决方法!

```
message MapFieldEntry {  
  key_type key = 1;  
  value_type value = 2;
}
repeated MapFieldEntry map_field = N;
```



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

推荐阅读更多精彩内容

  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,580评论 18 139
  • http://blog.csdn.net/yu616568/article/details/50993491 Ap...
    blablablala阅读 2,422评论 0 2
  • 原文地址:https://developers.google.com/protocol-buffers/docs/...
    JohnShen阅读 11,504评论 2 5
  • 今天听一堂关于孩子教育的课程启发颇多,因为自己学习过幼儿教育,自认为在幼儿教育上没有什么大的问题,但今天听了老师的...
    晓蕊阅读 75评论 0 0
  • 2010-08-25 20:20:06 我以为我的温柔。能给你真的宇宙 我以为我能全力。填满你感情缺口 专心陪在你...
    国王的心事阅读 217评论 0 1