﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>BlogJava-j2ee绿洲-文章分类-GoogleProtocolBuffer</title><link>http://www.blogjava.net/livery/category/53051.html</link><description>找到属于自己的一片天空</description><language>zh-cn</language><lastBuildDate>Thu, 29 Nov 2012 08:37:21 GMT</lastBuildDate><pubDate>Thu, 29 Nov 2012 08:37:21 GMT</pubDate><ttl>60</ttl><item><title>google protocol buffer -2-.proto 定义规则</title><link>http://www.blogjava.net/livery/articles/392084.html</link><dc:creator>心情经纬</dc:creator><author>心情经纬</author><pubDate>Wed, 28 Nov 2012 23:41:00 GMT</pubDate><guid>http://www.blogjava.net/livery/articles/392084.html</guid><wfw:comment>http://www.blogjava.net/livery/comments/392084.html</wfw:comment><comments>http://www.blogjava.net/livery/articles/392084.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/livery/comments/commentRss/392084.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/livery/services/trackbacks/392084.html</trackback:ping><description><![CDATA[<div>message为主要关键字，类似于java中的class。<br />
<strong style="font-family: 'Times New Roman'; font-size: 18pt; ">定义简单message类型</strong></div>
<div>SearchRequest.proto定义了每个查询请求的消息格式，每个请求都会有查询关键词query，查询结果的页数，每页的结果数量这三个属性。于是</div>
<div></div>
<div>
<div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
-->message&nbsp;SearchRequest{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;required&nbsp;string&nbsp;query&nbsp;=&nbsp;1;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;optional&nbsp;int32&nbsp;page_number&nbsp;=&nbsp;2;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;optional&nbsp;int32&nbsp;result_per_page&nbsp;=3;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;repeated&nbsp;int32&nbsp;samples&nbsp;=&nbsp;4&nbsp;[packed=<span style="color: #0000FF; ">true</span>];&nbsp;&nbsp;&nbsp;&nbsp;<br />
}</div>
</div>
<div>message定义了三个field，每个field由名字和类型来组成。</div>
<div>
<ul>
     <li>指定field类型</li>
</ul>
</div>
<div>在这个例子中，SearchRequest的field都是基本类型，两个integer（page_number和result_per_page）和一个Stirng(query)，也可以指定复杂的类型属性，包括枚举和其它类型。</div>
<div>
<ul>
     <li>分配标签</li>
</ul>
</div>
<div>每个field都是唯一数字的标记，这是用来标记这个field在message二进制格式中的位置的，一旦使用就不能再修改顺序了。</div>
<div>注:标记从1-15只有一个字节编码，包括自增长属性（更多的见Protocol Buffer Encoding）</div>
<div><span style="white-space:pre">	</span>标记从16-2047占用两个字节。因此尽量频繁使用1-15，记住为未来的扩展留下一些位置。</div>
<div><span style="white-space:pre">	</span>最小的tag你可以定义为1，最大2的29次方-1 &nbsp;536870922.你同样不能使用19000-19999（这个位置已经被GPB自己实现），</div>
<div>
<ul>
     <li>指定field规则<br />
     </li>
</ul>
</div>
<div></div>
<div>
<div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
-->message&nbsp;SearchRequest{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;required&nbsp;string&nbsp;query&nbsp;=&nbsp;1<span style="color: #008000; ">;<br />
</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;optional&nbsp;int32&nbsp;page_number&nbsp;=&nbsp;2<span style="color: #008000; ">;<br />
</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;optional&nbsp;int32&nbsp;result_per_page&nbsp;=3<span style="color: #008000; ">;<br />
</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;repeated&nbsp;int32&nbsp;samples&nbsp;=&nbsp;4&nbsp;<span style="color: #800000; font-weight: bold; ">[</span><span style="color: #800000; ">packed=true</span><span style="color: #800000; font-weight: bold; ">]</span><span style="color: #008000; ">;</span><span style="color: #008000; ">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000; "><br />
</span>}</div>
由于历史原因，repeated字段如果是基本数字类型的话，不能有效地编码。现在代码可以使用特殊选项[packed=true]来得到更有效率的编码。</div>
<div>注：<span style="color: #3366ff; "> 由于required是永远的，应该非常慎重地给message某个字段设置为required。如果未来你希望停止写入或者输出某个required字段，那就会成为问题；因为旧的reader将以为没有这个字段无法初始化message，会丢掉这部分信息。一些来自google的工程师们指出使用required弊大于利，尽量使用optional和repeated。</span></div>
<div>这个观点并不是通用的。</div>
<div></div>
<div>
<ul>
     <li>更多message类型</li>
</ul>
</div>
<div>多个message类型能被定义在一个简单的.proto文件中，通常是创建具有关联关系的message时候这么作。</div>
<div></div>
<div>
<div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
-->message&nbsp;SearchRequest{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;required&nbsp;string&nbsp;query&nbsp;=&nbsp;1<span style="color: #008000; ">;<br />
</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;optional&nbsp;int32&nbsp;page_number&nbsp;=&nbsp;2<span style="color: #008000; ">;<br />
</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;optional&nbsp;int32&nbsp;result_per_page&nbsp;=3<span style="color: #008000; ">;<br />
</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;repeated&nbsp;int32&nbsp;samples&nbsp;=&nbsp;4&nbsp;<span style="color: #800000; font-weight: bold; ">[</span><span style="color: #800000; ">packed=true</span><span style="color: #800000; font-weight: bold; ">]</span><span style="color: #008000; ">;</span><span style="color: #008000; ">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000; "><br />
</span>}</div>
</div>
<div></div>
<div>
<ul>
     <li><strong>添加注释</strong></li>
</ul>
</div>
<div>使用c/C++ style</div>
<div></div>
<div></div>
<div>
<div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
-->message&nbsp;SearchRequest{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;required&nbsp;<span style="color: #0000FF; ">string</span>&nbsp;query&nbsp;=&nbsp;1;&nbsp;&nbsp;<span style="color: #008000; ">//<br />
</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;optional&nbsp;int32&nbsp;page_number&nbsp;=&nbsp;2;&nbsp;&nbsp;<span style="color: #008000; ">//</span><span style="color: #008000; ">&nbsp;which&nbsp;page&nbsp;number&nbsp;do&nbsp;we&nbsp;want?</span><span style="color: #008000; "><br />
</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;optional&nbsp;int32&nbsp;result_per_page&nbsp;=3;&nbsp;<span style="color: #008000; ">//</span><span style="color: #008000; ">&nbsp;Number&nbsp;of&nbsp;results&nbsp;to&nbsp;return&nbsp;per&nbsp;page?</span><span style="color: #008000; "><br />
</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;repeated&nbsp;int32&nbsp;samples&nbsp;=&nbsp;4&nbsp;[packed=<span style="color: #0000FF; ">true</span>];&nbsp;&nbsp;&nbsp;&nbsp;<br />
}</div>
</div>
<div></div>
<div>
<ul>
     <li><strong>.proto文件自动生成代码</strong></li>
</ul>
</div>
<div>protocol buffer编译一个proto文件，生成对应语言的代码。</div>
<div>大概包括各个字段的get和set方法，序列化message到输出流的方法，从输入流转成message的方法。</div>
<div>C++，为每个proto生成一个.h和.cc文件</div>
<div>Java，为每个proto生成一个.java文件</div>
<div>Python，有点不同，生成一个module</div>
<div></div>
<div>
<ul>
     <li><strong>基本属性 &nbsp;</strong><br />
     </li>
</ul>
</div>
<div><img src="http://www.blogjava.net/images/blogjava_net/livery/130DE186-D4A7-4976-BA0C-4D2DEF887710.png" width="294" height="112" alt="" /></div>
<div>
<ul>
     <li><strong>optional字段和默认值</strong></li>
</ul>
</div>
<div>当含有optional字段的message从流转换成对象的时候，如果没有包含optional字段的数据，那么对象的optional字段会设置成默认值。</div>
<div>默认值可以作为message的描述出现。举个例子：</div>
<div>
<div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
-->optional&nbsp;int32&nbsp;result_per_page&nbsp;=&nbsp;3&nbsp;<span style="color: #800000; font-weight: bold; ">[</span><span style="color: #800000; ">default&nbsp;=&nbsp;10</span><span style="color: #800000; font-weight: bold; ">]</span><span style="color: #008000; ">;</span></div>
</div>
<div>如
<div style="display: inline-block; ">pasting</div>
果没有指定默认值的话，string 默认为空串，bool 默认为false，数字类型默认0，枚举类型，默认为类型定义中的第一个值，</div>
<div></div>
<div>
<ul>
     <li><strong>Enumerations</strong></li>
</ul>
</div>
<div>如果字段的属性值是固定的几个值，可以使用枚举<br />
<div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
-->message&nbsp;SearchRequest&nbsp;{<br />
&nbsp;&nbsp;required&nbsp;<span style="color: #0000FF; ">string</span>&nbsp;query&nbsp;=&nbsp;1;<br />
&nbsp;&nbsp;optional&nbsp;int32&nbsp;page_number&nbsp;=&nbsp;2;<br />
&nbsp;&nbsp;optional&nbsp;int32&nbsp;result_per_page&nbsp;=&nbsp;3&nbsp;[<span style="color: #0000FF; ">default</span>&nbsp;=&nbsp;10];<br />
&nbsp;&nbsp;<span style="color: #0000FF; ">enum</span>&nbsp;Corpus&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;UNIVERSAL&nbsp;=&nbsp;0;<br />
&nbsp;&nbsp;&nbsp;&nbsp;WEB&nbsp;=&nbsp;1;<br />
&nbsp;&nbsp;&nbsp;&nbsp;IMAGES&nbsp;=&nbsp;2;<br />
&nbsp;&nbsp;&nbsp;&nbsp;LOCAL&nbsp;=&nbsp;3;<br />
&nbsp;&nbsp;&nbsp;&nbsp;NEWS&nbsp;=&nbsp;4;<br />
&nbsp;&nbsp;&nbsp;&nbsp;PRODUCTS&nbsp;=&nbsp;5;<br />
&nbsp;&nbsp;&nbsp;&nbsp;VIDEO&nbsp;=&nbsp;6;<br />
&nbsp;&nbsp;}<br />
&nbsp;&nbsp;optional&nbsp;Corpus&nbsp;corpus&nbsp;=&nbsp;4&nbsp;[<span style="color: #0000FF; ">default</span>&nbsp;=&nbsp;WEB];<br />
}</div>
</div>
<div></div>
<div>
<ul>
     <li><strong>自定义消息类型</strong></li>
</ul>
</div>
<div>可以使用message类型做字段的属性，看例子：</div>
<div>
<div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
-->message&nbsp;SearchResponse&nbsp;{<br />
&nbsp;&nbsp;repeated&nbsp;Result&nbsp;result&nbsp;=&nbsp;1;<br />
}<br />
message&nbsp;Result&nbsp;{<br />
&nbsp;&nbsp;required&nbsp;<span style="color: #0000FF; ">string</span>&nbsp;url&nbsp;=&nbsp;1;<br />
&nbsp;&nbsp;optional&nbsp;<span style="color: #0000FF; ">string</span>&nbsp;title&nbsp;=&nbsp;2;<br />
&nbsp;&nbsp;repeated&nbsp;<span style="color: #0000FF; ">string</span>&nbsp;snippets&nbsp;=&nbsp;3;<br />
}</div>
</div>
<div></div>
<div></div>
<div>
<ul>
     <li><strong>import 定义</strong></li>
</ul>
</div>
<div>上面的例子SearchResponse 与Result在一个.proto文件中。其实也可以使用另一个.proto文件来定义字段类型。</div>
<div>你可以通过import来定义。</div>
<div>
<div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #0000FF; ">import</span>&nbsp;"myproject/other_protos.proto";</div>
</div>
<div></div>
<div>protocol编译器查找引入文件是通过编译器的命令参数 -I/--proto_path</div>
<div>如果没有指定，就在protoc执行目录下寻找。</div>
<div>The protocol compiler searches for imported files in a set of directories specified on the protocol compiler command line using the -I/--proto_path flag.&nbsp;</div>
<div>If no flag was given, it looks in the directory in which the compiler was invoked.&nbsp;</div>
<div>In general you should set the --proto_path flag to the root of your project and use fully qualified names for all imports.</div>
<div></div>
<div>
<ul>
     <li><strong>内部类</strong></li>
</ul>
</div>
<div>你可以定义和使用内部message类。</div>
<div>
<div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
-->message&nbsp;SearchResponse&nbsp;{<br />
&nbsp;&nbsp;message&nbsp;Result&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;required&nbsp;string&nbsp;url&nbsp;=&nbsp;1;<br />
&nbsp;&nbsp;&nbsp;&nbsp;optional&nbsp;string&nbsp;title&nbsp;=&nbsp;2;<br />
&nbsp;&nbsp;&nbsp;&nbsp;repeated&nbsp;string&nbsp;snippets&nbsp;=&nbsp;3;<br />
&nbsp;&nbsp;}<br />
&nbsp;&nbsp;repeated&nbsp;Result&nbsp;result&nbsp;=&nbsp;1;<br />
}</div>
</div>
<div></div>
<div>如果要引用内部类，则通过parent.type方式来调用</div>
<div>
<div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
-->message&nbsp;SomeOtherMessage&nbsp;{<br />
&nbsp;&nbsp;optional&nbsp;SearchResponse.Result&nbsp;result&nbsp;=&nbsp;1;<br />
}</div>
</div>
<div></div>
<div>还可以很深、很深的内部类</div>
<div>
<div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
-->message&nbsp;Outer&nbsp;{&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #008000; ">//</span><span style="color: #008000; ">&nbsp;Level&nbsp;0</span><span style="color: #008000; "><br />
</span>&nbsp;&nbsp;message&nbsp;MiddleAA&nbsp;{&nbsp;&nbsp;<span style="color: #008000; ">//</span><span style="color: #008000; ">&nbsp;Level&nbsp;1</span><span style="color: #008000; "><br />
</span>&nbsp;&nbsp;&nbsp;&nbsp;message&nbsp;Inner&nbsp;{&nbsp;&nbsp;&nbsp;<span style="color: #008000; ">//</span><span style="color: #008000; ">&nbsp;Level&nbsp;2</span><span style="color: #008000; "><br />
</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;required&nbsp;int64&nbsp;ival&nbsp;=&nbsp;1;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;optional&nbsp;bool&nbsp;&nbsp;booly&nbsp;=&nbsp;2;<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;}<br />
&nbsp;&nbsp;message&nbsp;MiddleBB&nbsp;{&nbsp;&nbsp;<span style="color: #008000; ">//</span><span style="color: #008000; ">&nbsp;Level&nbsp;1</span><span style="color: #008000; "><br />
</span>&nbsp;&nbsp;&nbsp;&nbsp;message&nbsp;Inner&nbsp;{&nbsp;&nbsp;&nbsp;<span style="color: #008000; ">//</span><span style="color: #008000; ">&nbsp;Level&nbsp;2</span><span style="color: #008000; "><br />
</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;required&nbsp;int32&nbsp;ival&nbsp;=&nbsp;1;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;optional&nbsp;bool&nbsp;&nbsp;booly&nbsp;=&nbsp;2;<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;}<br />
}</div>
</div>
<div></div>
<div>
<ul>
     <li><strong>Groups&nbsp;</strong></li>
</ul>
&nbsp;废弃的属性，了解即可，采用内部类代替。</div>
<div>
<div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
-->message&nbsp;SearchResponse&nbsp;{<br />
&nbsp;&nbsp;repeated&nbsp;group&nbsp;Result&nbsp;=&nbsp;1&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;required&nbsp;string&nbsp;url&nbsp;=&nbsp;2;<br />
&nbsp;&nbsp;&nbsp;&nbsp;optional&nbsp;string&nbsp;title&nbsp;=&nbsp;3;<br />
&nbsp;&nbsp;&nbsp;&nbsp;repeated&nbsp;string&nbsp;snippets&nbsp;=&nbsp;4;<br />
&nbsp;&nbsp;}<br />
}</div>
</div>
<strong style="font-family: 'Times New Roman'; font-size: 18pt; "><br /></strong><div><br /><div></div><div><span style="font-family: 'Times New Roman'; font-size: 18pt; "><strong>Extentions</strong></span></div><div>extensions 声明一个消息中的一定范围的field的顺序数字用于进行扩展。其它人可以在自己的.proto文件中重新定义这些消息field，而不需要去修改原始的.proto文件</div><div><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />-->message&nbsp;Foo&nbsp;{<br />&nbsp;&nbsp;<span style="color: #008000; ">//</span><span style="color: #008000; ">&nbsp;<img src="http://www.blogjava.net/Images/dot.gif" alt="" /></span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;extensions&nbsp;100&nbsp;to&nbsp;199;<br />}</div></div><div>这些说明100-199的field是保留的。其它用户可以用这些field在他们自己的.proto文件中添加新的fields给Foo。举例：</div><div><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />-->extend&nbsp;Foo&nbsp;{<br />&nbsp;&nbsp;optional&nbsp;int32&nbsp;bar&nbsp;=&nbsp;126;<br />}</div></div><div>说明 Foo有一个optional的int32类型的名称为bar的field &nbsp; </div><div>当Foo的message编码后，数据格式就跟用户在Foo中定义一个新的field完全一样。但是你在程序中访问extension field的方式与访问正常的属性略微有点不同。生成的extensions的访问代码是不同的。举例：c++中如何set属性bar的值：<br /><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />-->Foo&nbsp;foo;<br />foo.SetExtension(bar,15);</div></div><div>同样，Foo 定义了模板访问器 &nbsp;HasExtendsion(),ClearExtension(),GetExtension(),MutableExtension(),AddExtension().</div><div>所有 访问 &nbsp; &nbsp; &nbsp;&nbsp;<br />注：<span style="color: #0000ff; "> extensions能使用任何field类型，包括自定义消息类型。</span></div><div><ul><li><strong>内嵌的extensions</strong></li></ul></div><div>能声明extensions在另一个message中<br /><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />-->message&nbsp;Baz&nbsp;{<br />&nbsp;&nbsp;extend&nbsp;Foo&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;optional&nbsp;int32&nbsp;bar&nbsp;=&nbsp;126<span style="color: #008000; ">;<br /></span>&nbsp;&nbsp;}<br />&nbsp;&nbsp;<img src="http://www.blogjava.net/Images/dot.gif" alt="" /><br />}</div></div><div>在这个例子中, the C++ 代码访问访问这个属性:<br /><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />-->Foo&nbsp;foo;<br />foo.SetExtension(Baz::bar,&nbsp;15);</div></div><div></div><div>换句话说，这么做唯一影响是bar定义在了Baz的范围之内。</div><div>注意：<span style="color: #0000ff; ">容易混淆的地方 声明一个消息内部的继承类并不意味着外部类和extended类有任何关系。</span><span style="color: #0000ff; ">特别 以上的例子并不意味着Baz是任何Foo的子类。这些只是意味着符号bar是声明在Baz的范围之内的，</span><span style="color: #0000ff; ">它看起来更像是个静态成员。</span></div><div>一个通用的模式是在extensions的field范围内来定义extensions，举例说明，这里有一个Foo的extension作为Baz的一部分的属性类型是Baz<br /><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />-->message&nbsp;Baz&nbsp;{<br />&nbsp;&nbsp;extend&nbsp;Foo&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;optional&nbsp;Baz&nbsp;foo_ext&nbsp;=&nbsp;127<span style="color: #008000; ">;<br /></span>&nbsp;&nbsp;}<br />&nbsp;&nbsp;<img src="http://www.blogjava.net/Images/dot.gif" alt="" /><br />}</div></div><div>没有必要非得在message内部定义一个extension的类型。你也可以这么做：<br /><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />-->message&nbsp;Baz&nbsp;{<br />&nbsp;&nbsp;<img src="http://www.blogjava.net/Images/dot.gif" alt="" /><br />}<br />//&nbsp;This&nbsp;can&nbsp;even&nbsp;be&nbsp;in&nbsp;a&nbsp;different&nbsp;file.<br />extend&nbsp;Foo&nbsp;{<br />&nbsp;&nbsp;optional&nbsp;Baz&nbsp;foo_baz_ext&nbsp;=&nbsp;127<span style="color: #008000; ">;<br /></span>}</div></div><div></div><div>事实上，上面的这个语法更加有效地避免混淆。正如上文所述，内部的那种语法语法对于不是熟悉extensions的人来说，经常会错认为子类。</div><div></div><div><ul><li><strong>选择Extension 顺序数字</strong></li></ul></div><div>非常重要的一点是双方不能使用同样数字添加一样的message类型，这样extension会被解释为错误类型。</div><div>可能需要有一个关于field的数字顺序的约定来保证你的project不会发生这样的重复的问题。</div><div>如果你的field数字比较大的话，可以使用max来指定你的textension范围上升到最大的范围</div><div><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />-->message&nbsp;Foo&nbsp;{<br />&nbsp;&nbsp;extensions&nbsp;1000&nbsp;to&nbsp;max<span style="color: #008000; ">;<br /></span>}<br />max&nbsp;is&nbsp;229&nbsp;-&nbsp;1,&nbsp;or&nbsp;536,870,911.</div></div><div>19000-19999是protocol buffers的使用的字段，所以这个范围内的数字需要区别开来。</div><div></div><div><strong style="font-family: 'Times New Roman'; font-size: 18pt; ">Packages</strong></div><div>可以给一个.protol文件增加一个optional的package描述，来保证message尽量不会出现名字相同的重名。</div><div><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />-->package&nbsp;foo.bar<span style="color: #008000; ">;<br /></span>message&nbsp;Open&nbsp;{&nbsp;<br /><img src="http://www.blogjava.net/Images/dot.gif" alt="" />&nbsp;<br />}</div></div><div>也可以在指定field类型的时候使用</div><div></div><div><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />-->message&nbsp;Foo&nbsp;{<br />&nbsp;&nbsp;<img src="http://www.blogjava.net/Images/dot.gif" alt="" /><br />&nbsp;&nbsp;required&nbsp;foo.bar.Open&nbsp;open&nbsp;=&nbsp;1<span style="color: #008000; ">;<br /></span>&nbsp;&nbsp;<img src="http://www.blogjava.net/Images/dot.gif" alt="" /><br />}</div></div><div></div><div>package会根据选择的语言来生成不同的代码：</div><div><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />-->C++ &nbsp; &nbsp; &nbsp;生成的classes是用C++的namespace来区分的。举例：Open&nbsp;would&nbsp;be&nbsp;in&nbsp;the&nbsp;namespace&nbsp;foo::bar。<br />Java &nbsp; &nbsp; &nbsp;package用于Java的package，除非你单独的指定一个option&nbsp;java_package&nbsp;在.proto文件中。<br />Python &nbsp; package是被忽略的，因为Python的modules是通过它们的文件位置来组织的。</div></div><div></div><div><ul><li><strong>Packages和name&nbsp;</strong></li></ul></div><div>在protocol buffer中package名称的方案看起来像C++，首先，最里面的范围被搜索，然后搜索次一级的范围，</div><div>每个package被认为在他的父package内。一个. （.foo.bar.Baz）意味着从最外层开始.</div><div></div><div><strong style="font-family: 'Times New Roman'; font-size: 18pt; ">options</strong></div><div>在一个proto文件中，还可以存在一些options。Options不能改变一个声明的整体的意义，但是可以影响一定的上下文。</div><div>可用的options的完整list定义在 Google/protobuf/descriptor.proto</div><div></div><div>一些options是第一级的，意味着它们应该被写在顶级范围，而不是在任何message,enum，sercie的定义中。</div><div>一些options是message级别的，意味着它们应该被写入message的描述中，</div><div>一些options是field-level级别的，意味着它们应该被写入field的描述中，</div><div>options也可以被写入enum类型中，enum的值，service类型 和service方法；</div><div></div><div>列举了常用的options：</div><div><span style="color: #339966; ">java_package(file option)</span></div><div><span style="white-space:pre">		</span>定义生成的java class的package。如果在proto文件中没有明确的java_package选项，那么默认会使用package关键字指定的package名。</div><div>但是proto package通常不会好于Java packages，因为proto packages通常不会以domain名称开始。</div><div>如果不生成java代码，此选项没有任何影响。</div><div><span style="white-space:pre">		</span>option java_package = "com.example.foo";</div><div><span style="color: #339966; ">java_outer_classname:(file option)</span></div><div><span style="white-space:pre">		</span>指定想要生成的class名称，如果此参数没有指定的话，那么默认使用.proto文件名来做为类名，并且采用驼峰表示（比如：foo_bar.proto 为 FooBar.java）</div><div>如果不生成java代码，此选项没有影响。</div><div><span style="white-space:pre">		</span>option java_outer_classname = "Ponycopter";</div><div><span style="color: #339966; ">optimize_for (file option)</span></div><div><span style="white-space:pre">		</span>可以设置为speed、code_size或者lite_runtime.</div><div><span style="white-space:pre">	</span><span style="color: #33cccc; ">SPEED</span>:默认。protocol编译器会生成classes代码，提供了message类的序列化、转换和其它通用操作。这个代码是被高度优化过的。</div><div><span style="white-space:pre">	</span><span style="color: #33cccc; ">CODE_SIZE:&nbsp;</span>protocol编译器会生成最小的classes，并且依赖共享、基于反射的代码实现序列化、转换和其它通用操作。生成的classes代码小于speed，但是操作会慢一点。classes会实现跟SPEED模式一样的公共API。这个模式通常用在一个应用程序包含了大量的proto文件，但是并不需要所有的代码都执行得很快</div><div><span style="white-space:pre">	</span><span style="color: #33cccc; ">LITE_RUNTIME:&nbsp;</span>protocol编译器会生成仅仅依赖 lite 运行库（libprotobuf-lite代替libprotobuf）。lite运行时比全量库小很多，省略了某种特性（如： descriptors and reflection）这个选项对于运行在像移动手机这种有约束平台上的应用更有效。 编译器仍然会对所有方法生成非常快的代码实现，就像SPEED模式一样。protocol编译器会用各种语言来实现MessageList接口，但是这个接口仅仅提供了其它模式实现的Message接口的一部分方法子集。</div><div><span style="white-space:pre">例子<br /></span><span style="background-color: #eeeeee; font-size: 13px; ">option&nbsp;optimize_for&nbsp;</span><span style="background-color: #eeeeee; font-size: 13px; ">=</span><span style="background-color: #eeeeee; font-size: 13px; ">&nbsp;CODE_SIZE</span><span style="font-size: 13px; color: #008000; ">;</span><span style="white-space:pre">	</span></div><div><span style="color: #339966; ">cc_generic_services, java_generic_services, py_generic_services (file options)</span></div><div>无论如何，protoc编译器会生成基于C++,Java,Python的抽象service代码，这些默认都是true。截至到2.3.0版本，RPC实现提供了代码生成插件去生成代码，不再使用抽象类。</div><div><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #008000; ">//&nbsp;This&nbsp;file&nbsp;relies&nbsp;on&nbsp;plugins&nbsp;to&nbsp;generate&nbsp;service&nbsp;code.</span><br />option&nbsp;cc_generic_services&nbsp;=&nbsp;false<span style="color: #008000; ">;<br /></span>option&nbsp;java_generic_services&nbsp;=&nbsp;false<span style="color: #008000; ">;<br /></span>option&nbsp;py_generic_services&nbsp;=&nbsp;false<span style="color: #008000; ">;</span></div></div><div></div><div><span style="color: #339966; ">message_set_wire_format (message option)</span></div><div><span style="white-space:pre">		</span>如果设置为true，消息使用不同的二进制格式来兼容谷歌内部使用的称为MessageSet的旧格式。用户在google以外使用，将不再需要使用这个option。</div><div>消息必须按照以下声明<br /><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />-->message&nbsp;Foo&nbsp;{<br />&nbsp;&nbsp;option&nbsp;message_set_wire_format&nbsp;=&nbsp;true<span style="color: #008000; ">;<br /></span>&nbsp;&nbsp;extensions&nbsp;4&nbsp;to&nbsp;max<span style="color: #008000; ">;<br /></span>}</div></div><div><span style="color: #339966; ">packed (field option)</span></div><div><span style="white-space:pre">		</span>如果设置为true， 一个repeated的基本integer类型的field，会使用一种更加紧凑的压缩编码。请注意，在2.3.0版之前，protocol生成的解析逻辑收到未预期的压缩的数据将会忽略掉。因此，改变一个已经存在的field，一定会破坏其线性兼容性。在2.3.0以后，这种改变就是安全的，解析逻辑可以识别压缩和不压缩的格式，但是，一定要小心那些使用原先旧版本的protocol的程序。</div><div><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />-->repeated&nbsp;int32&nbsp;samples&nbsp;=&nbsp;4&nbsp;<span style="color: #800000; font-weight: bold; ">[</span><span style="color: #800000; ">packed=true</span><span style="color: #800000; font-weight: bold; ">]</span><span style="color: #008000; ">;</span></div></div><div>deprecated (field option):</div><div><span style="white-space:pre">		</span>如果设置为true，表示这个field被废弃，应该使用新代码。大多数语言中，这个没有任何影响。在java中，会生成@Deprecated的注释。未来，其它语言代码在field的访问方法上也会生成相应的注释。</div><div><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />-->optional&nbsp;int32&nbsp;old_field&nbsp;=&nbsp;6&nbsp;<span style="color: #800000; font-weight: bold; ">[</span><span style="color: #800000; ">deprecated=true</span><span style="color: #800000; font-weight: bold; ">]</span><span style="color: #008000; ">;</span></div></div><div></div><div><ul><li><strong>自定义options</strong></li></ul></div><div></div><div>protocol buffer还允许你自定义options。这是个高级特性，大多数人并不需要。options其实都定义在 google/protobuf/descriptor.proto文件中。</div><div>自定义的options是简单的，继承这些messages</div><div><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />-->import&nbsp;"google/protobuf/descriptor.proto"<span style="color: #008000; ">;<br /></span>extend&nbsp;google.protobuf.MessageOptions&nbsp;{<br />&nbsp;&nbsp;optional&nbsp;string&nbsp;my_option&nbsp;=&nbsp;51234<span style="color: #008000; ">;<br /></span>}<br />message&nbsp;MyMessage&nbsp;{<br />&nbsp;&nbsp;option&nbsp;(my_option)&nbsp;=&nbsp;"Hello&nbsp;world!"<span style="color: #008000; ">;<br /></span>}</div></div><div></div><div>这里我们定义了一个message级别的消息选项，当使用这个options的时候，选项的名称必须用括号括起来，以表明它是一个extension。</div><div>我们在C++中读取my_option的值就像下面这样：</div><div><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #0000FF; ">string</span>&nbsp;value&nbsp;=&nbsp;MyMessage::descriptor()-&gt;options().GetExtension(my_option);</div></div><div>这里，MyMessage::descriptor()-&gt;options()返回的MessageOptions protocol类型 message。</div><div>读取自定义就如同读取继承属性一样。</div><div>在Java中</div><div><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />-->String&nbsp;value&nbsp;=&nbsp;MyProtoFile.MyMessage.getDescriptor().getOptions().getExtension(MyProtoFile.myOption);</div></div><div>自定义options可以对任何message的组成元素进行定义 </div><div><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />-->import&nbsp;"google/protobuf/descriptor.proto"<span style="color: #008000; ">;<br /></span>extend&nbsp;google.protobuf.FileOptions&nbsp;{<br />&nbsp;&nbsp;optional&nbsp;string&nbsp;my_file_option&nbsp;=&nbsp;50000<span style="color: #008000; ">;<br /></span>}<br />extend&nbsp;google.protobuf.MessageOptions&nbsp;{<br />&nbsp;&nbsp;optional&nbsp;int32&nbsp;my_message_option&nbsp;=&nbsp;50001<span style="color: #008000; ">;<br /></span>}<br />extend&nbsp;google.protobuf.FieldOptions&nbsp;{<br />&nbsp;&nbsp;optional&nbsp;float&nbsp;my_field_option&nbsp;=&nbsp;50002<span style="color: #008000; ">;<br /></span>}<br />extend&nbsp;google.protobuf.EnumOptions&nbsp;{<br />&nbsp;&nbsp;optional&nbsp;bool&nbsp;my_enum_option&nbsp;=&nbsp;50003<span style="color: #008000; ">;<br /></span>}<br />extend&nbsp;google.protobuf.EnumValueOptions&nbsp;{<br />&nbsp;&nbsp;optional&nbsp;uint32&nbsp;my_enum_value_option&nbsp;=&nbsp;50004<span style="color: #008000; ">;<br /></span>}<br />extend&nbsp;google.protobuf.ServiceOptions&nbsp;{<br />&nbsp;&nbsp;optional&nbsp;MyEnum&nbsp;my_service_option&nbsp;=&nbsp;50005<span style="color: #008000; ">;<br /></span>}<br />extend&nbsp;google.protobuf.MethodOptions&nbsp;{<br />&nbsp;&nbsp;optional&nbsp;MyMessage&nbsp;my_method_option&nbsp;=&nbsp;50006<span style="color: #008000; ">;<br /></span>}<br />option&nbsp;(my_file_option)&nbsp;=&nbsp;"Hello&nbsp;world!"<span style="color: #008000; ">;<br /></span>message&nbsp;MyMessage&nbsp;{<br />&nbsp;&nbsp;option&nbsp;(my_message_option)&nbsp;=&nbsp;1234<span style="color: #008000; ">;<br /></span>&nbsp;&nbsp;optional&nbsp;int32&nbsp;foo&nbsp;=&nbsp;1&nbsp;<span style="color: #800000; font-weight: bold; ">[</span><span style="color: #800000; ">(my_field_option)&nbsp;=&nbsp;4.5</span><span style="color: #800000; font-weight: bold; ">]</span><span style="color: #008000; ">;<br /></span>&nbsp;&nbsp;optional&nbsp;string&nbsp;bar&nbsp;=&nbsp;2<span style="color: #008000; ">;<br /></span>}<br />enum&nbsp;MyEnum&nbsp;{<br />&nbsp;&nbsp;option&nbsp;(my_enum_option)&nbsp;=&nbsp;true<span style="color: #008000; ">;<br /></span>&nbsp;&nbsp;FOO&nbsp;=&nbsp;1&nbsp;<span style="color: #800000; font-weight: bold; ">[</span><span style="color: #800000; ">(my_enum_value_option)&nbsp;=&nbsp;321</span><span style="color: #800000; font-weight: bold; ">]</span><span style="color: #008000; ">;<br /></span>&nbsp;&nbsp;BAR&nbsp;=&nbsp;2<span style="color: #008000; ">;<br /></span>}<br />message&nbsp;RequestType&nbsp;{}<br />message&nbsp;ResponseType&nbsp;{}<br />service&nbsp;MyService&nbsp;{<br />&nbsp;&nbsp;option&nbsp;(my_service_option)&nbsp;=&nbsp;FOO<span style="color: #008000; ">;<br /></span>&nbsp;&nbsp;rpc&nbsp;MyMethod(RequestType)&nbsp;returns(ResponseType)&nbsp;{<br /><span style="color: #008000; ">&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;Note:&nbsp;&nbsp;my_method_option&nbsp;has&nbsp;type&nbsp;MyMessage.&nbsp;&nbsp;We&nbsp;can&nbsp;set&nbsp;each&nbsp;field</span><br /><span style="color: #008000; ">&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;&nbsp;&nbsp;within&nbsp;it&nbsp;using&nbsp;a&nbsp;separate&nbsp;</span><span style="color: #008000; ">"</span><span style="color: #008000; ">option</span><span style="color: #008000; ">"</span><span style="color: #008000; ">&nbsp;line.</span><br />&nbsp;&nbsp;&nbsp;&nbsp;option&nbsp;(my_method_option).foo&nbsp;=&nbsp;567<span style="color: #008000; ">;<br /></span>&nbsp;&nbsp;&nbsp;&nbsp;option&nbsp;(my_method_option).bar&nbsp;=&nbsp;"Some&nbsp;string"<span style="color: #008000; ">;<br /></span>&nbsp;&nbsp;}<br />}</div></div><div>如果想使用在package里面的自定义的option，必须要option前使用包名，如下</div><div><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #008000; ">//&nbsp;foo.proto</span><br />import&nbsp;"google/protobuf/descriptor.proto"<span style="color: #008000; ">;<br /></span>package&nbsp;foo<span style="color: #008000; ">;<br /></span>extend&nbsp;google.protobuf.MessageOptions&nbsp;{<br />&nbsp;&nbsp;optional&nbsp;string&nbsp;my_option&nbsp;=&nbsp;51234<span style="color: #008000; ">;<br /></span>}<br /><span style="color: #008000; ">//&nbsp;bar.proto</span><br />import&nbsp;"foo.proto"<span style="color: #008000; ">;<br /></span>package&nbsp;bar<span style="color: #008000; ">;<br /></span>message&nbsp;MyMessage&nbsp;{<br />&nbsp;&nbsp;option&nbsp;(foo.my_option)&nbsp;=&nbsp;"Hello&nbsp;world!"<span style="color: #008000; ">;<br /></span>}</div></div><div></div><div>最后一件事：既然自定义的options是extensions，他们必须指定field number就像其它field或者extension一样。如果你要在公共应用中使用自定义的options，那么一定要确认你的field numbers是全局唯一的</div><div>你能通过多选项带有一个extension 把它们放入一个子message中</div><div><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />-->message&nbsp;FooOptions&nbsp;{<br />&nbsp;&nbsp;optional&nbsp;int32&nbsp;opt1&nbsp;=&nbsp;1<span style="color: #008000; ">;<br /></span>&nbsp;&nbsp;optional&nbsp;string&nbsp;opt2&nbsp;=&nbsp;2<span style="color: #008000; ">;<br /></span>}<br />extend&nbsp;google.protobuf.FieldOptions&nbsp;{<br />&nbsp;&nbsp;optional&nbsp;FooOptions&nbsp;foo_options&nbsp;=&nbsp;1234<span style="color: #008000; ">;<br /></span>}<br /><span style="color: #008000; ">//&nbsp;usage:</span><br />message&nbsp;Bar&nbsp;{<br />&nbsp;&nbsp;optional&nbsp;int32&nbsp;a&nbsp;=&nbsp;1&nbsp;<span style="color: #800000; font-weight: bold; ">[</span><span style="color: #800000; ">(foo_options.opt1)&nbsp;=&nbsp;123,&nbsp;(foo_options.opt2)&nbsp;=&nbsp;"baz"</span><span style="color: #800000; font-weight: bold; ">]</span><span style="color: #008000; ">;<br /></span>&nbsp;<span style="color: #008000; ">&nbsp;//&nbsp;alternative&nbsp;aggregate&nbsp;syntax&nbsp;(uses&nbsp;TextFormat):</span><br />&nbsp;&nbsp;optional&nbsp;int32&nbsp;b&nbsp;=&nbsp;2&nbsp;<span style="color: #800000; font-weight: bold; ">[</span><span style="color: #800000; ">(foo_options)&nbsp;=&nbsp;{&nbsp;opt1:&nbsp;123&nbsp;opt2:&nbsp;"baz"&nbsp;}</span><span style="color: #800000; font-weight: bold; ">]</span><span style="color: #008000; ">;<br /></span>}</div></div><div></div><div></div><div><strong style="font-family: 'Times New Roman'; font-size: 18pt; ">生成class代码</strong></div><div>为了生成java、python、C++代码，你需要运行protoc编译器 protoc 编译.proto文件。</div><div>编译器运行命令：</div><div><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />-->protoc&nbsp;--proto_path=IMPORT_PATH&nbsp;--cpp_out=DST_DIR&nbsp;--java_out=DST_DIR&nbsp;--python_out=DST_DIR&nbsp;path/to/file.proto</div></div><div><span style="white-space:pre">	</span>import_path 查找proto文件的目录，如果省略的话，就是当前目录。存在多个引入目录的话，可以使用--proto_path参数来多次指定，</div><div><span style="white-space:pre">	</span>-I=IMPORT_PATH就是--proto_path的缩写</div><div>输出目录</div><div><span style="white-space:pre">	</span>--cpp_out &nbsp; &nbsp; &nbsp; 生成C++代码在DST_DIR目录</div><div><span style="white-space:pre">	</span>--java_out &nbsp; &nbsp; &nbsp;生成Java代码在DST_DIR目录</div><div><span style="white-space:pre">	</span>--python_out &nbsp; &nbsp;生成Python代码在DST_DIR目录</div><div>有个额外的好处，如果DST是.zip或者.jar结尾，那么编译器将会按照给定名字输入到一个zip压缩格式的文件中。</div><div>输出到.jar会有一个jar指定的manifest文件。注意 <span style="color: #3366ff; ">如果输出文件已经存在，它将会被覆盖；编译器的智能不足以自动添加文件到一个存在的压缩文件中。</span></div><div>你必须提供一个或者多个.proto文件用作输入。虽然文件命名关联到当前路径，每个文件必须在import_path路径中一边编译器能规定它的规范名称<br /><br /><br /><strong style="font-family: 'Times New Roman'; font-size: 18pt; ">更新message</strong><div>如果一个message 不再满足所有需要，需要对字段进行调整.(举例:对message增加一个额外的字段，但是仍然有支持旧格式message的代码在运行)</div><div>要注意以下几点:<br />1、不要修改已经存在字段的数字顺序标示</div><div>2、可以增加optional或者repeated的新字段。这么做以后，所有通过旧格式message序列化的数据都可以通过新代码来生成对应的对象，正如他们不会丢失任何required元素。</div><div>你应该为这些元素添加合理的默认值，以便新代码可以与旧代码生成的消息交互。 新代码创建的消息中旧代码不存在的字段，在解析的时候，旧代码会忽略掉新增的字段。</div><div>无论如何，未知的field不会被丢弃，如果message晚点序列化，为。</div><div>注意 未知field对于Python来说当前不可用。</div><div>3、非required字段都可以转为extension ，反之亦然，只要type和number保持不变。</div><div>4、int32, uint32, int64, uint64, and bool 是全兼容的。这意味着你能改变一个field从这些类型中的一个改变为另一个，而不用考虑会打破向前、向后兼容性。</div><div>如果一个数字是通过网络传输而来的相应类型转换，你将会遇到type在C++中遇到的问题（e.g. if a 64-bit number is read as an int32, it will be truncated to 32 bits） &nbsp; &nbsp; &nbsp;</div><div>5、sint32 and sint64 彼此兼容,但是不能兼容其它integer类型.</div><div>6、string and bytes 在UTF-8编码下是兼容的.&nbsp;</div><div>7、如果bytes包含一个message的编码,内嵌message与bytes兼容.</div><div>8、fixed32 兼容 sfixed32, &nbsp;fixed64 兼容 sfixed64.</div><div>9、optional 兼容 repeated. 用一个repeat字段的编码结果作为输入,认为这个字段是可选择的客户端会这样处理,如果是原始类型的话,获得最后的输入作为相应的option值;如果是message 类型,合并所有输入元素.&nbsp;</div><div>10、更改默认值通常是OK的.要记得默认值并不会通过网络发送,如果一个程序接受一个特定字段没有设置值的消息,应用将会使用自己的版本协议定义的默认值,不会看见发送者的默认值. &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;</div></div><div></div><div></div></div><img src ="http://www.blogjava.net/livery/aggbug/392084.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/livery/" target="_blank">心情经纬</a> 2012-11-29 07:41 <a href="http://www.blogjava.net/livery/articles/392084.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>