战魂小筑

讨论群:309800774 知乎关注:http://zhihu.com/people/sunicdavy 开源项目:https://github.com/davyxu

   :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理 ::
  257 随笔 :: 0 文章 :: 506 评论 :: 0 Trackbacks

本文编写时, Google 官方的 protobuf 版本是3.0.0beta

下面介绍下proto3的一些细节变化

Proto3的语法变化

语法标记

这个版本的protoc的protobuf编译器已经可以支持proto2语法和proto3的语法

如果你的proto文件没有添加syntax说明的话, 用这个版本的编译器会报错, 提示你默认proto2支持, 请添加语法标记

syntax = "proto2";

 

optional不需要了

只保留repeated标记数组类型, optional和required都被去掉了

实际使用证明, required的设计确实是蛋疼, C++的调试版会弹出assert,release版和optional也没啥区别

map支持

map编写格式为

map<key_type, value_type> map_field = N;
例如:
map<string, Project> projects = 3;
代码生成确认支持map, 这对于很多语言来说又可以偷懒了

字段default标记不能使用了

位于proto2语法的字段number后的[default=XX]

这个东西不能用了, 理由是:

对于同一段序列化后的数据, 如果序列化端的default和反序列化端的default描述不一样会导致最终结果完全不一致

即: 同一个数据两个结果, 这是不可预测的结果, 因此干掉这个特性

不过本人觉得, 对于游戏来说, 这个功能本身可以压缩很多数据,虽然会有隐患

 

枚举默认值一定是0

proto2里的默认值是枚举的第一个value对应的值, 不一定为0

proto3在你定义value时, 强制要求第一个值必须为0

这个修改为避免隐患还是有帮助的

泛型描述支持

any类型, 可以代表任何类型, 可以先读进来, 再进行解析, 没具体用, 步子跨大了怕扯到蛋

支持json序列化

这个极好, json再次被同化了

增加了多种语言支持

js, objc, ruby, C#等等

然而, C#版本的基础runtime库是用C# 6.0的语法写的,这对于Unity mono祖传2.0来说, 确实扯到蛋了,没法用

Protobuf现在使用CMAKE做配置系统

编译起来稍微麻烦, 还要下个被墙掉的cmake…

 

 

第三方库里对于proto3的变化

Golang的官方protobuf支持: https://github.com/golang/protobuf

生成代码中的结构体字段类型变化

对于proto2的文件, 生成的go代码中的结构体依然使用类型指针作为默认存储, 兼容老的系统

对于proto3的文件, 生成的go代码中的结构体直接使用字段作为默认存储, 不再使用GetXXX来作为字段值访问, 赋值时也无需使用proto.类型() 函数进行指针类型字段值创建.

这个调整很是方便, 但丢失了optional判断功能, 对应C++里就是hasXXX的功能, 不过好歹这个逻辑现在用的不多了

这个修改大概也是配合json序列化来做的, go默认的json序列化时, 无法使用proto2生成的结构体的, 因为都是指针,无法赋值..

 

新版protoc-gen-go的插件会生成descriptor的压缩数据

新插件会给每次生成的文件添加这样一段代码

var fileDescriptor0 = []byte{
    // 220 bytes of a gzipped FileDescriptorProto
    0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0x64, 0x8f, 0xcd, 0x4e, 0xc5, 0x20,
    0x10, 0x85, 0x53, 0xbd, 0x35, 0x32, 0xb7, 0xdd, 0x4c, 0x5c, 0xb0, 0x70, 0x71, 0xd3, 0xb8, 0x70,
    0x75, 0x17, 0xfa, 0x04, 0xc6, 0xd8, 0xb8, 0x50, 0x63, 0xa8, 0x2f, 0x80, 0xed, 0x44, 0x89, 0x28,
    0x04, 0xc6, 0xbf, 0x47, 0xf1, 0x6d, 0x95, 0x49, 0x8d, 0x4d, 0x5c, 0x01, 0xdf, 0x39, 0x7c, 0x30,
    0x00, 0x1c, 0x82, 0xdf, 0xc6, 0x14, 0x38, 0xe0, 0xaa, 0xec, 0xbb, 0x37, 0x68, 0x2e, 0x3e, 0x62,
    0x48, 0x7c, 0x49, 0x76, 0xa2, 0x84, 0x47, 0xd0, 0xde, 0x96, 0xf8, 0xee, 0x33, 0xd2, 0x8d, 0x7d,
    0x26, 0x5d, 0x6d, 0xaa, 0x63, 0x65, 0xda, 0xb8, 0x84, 0xd8, 0x41, 0x63, 0xc2, 0x7b, 0xef, 0xc8,
    0x4f, 0x52, 0xda, 0x91, 0x52, 0x93, 0x16, 0x0c, 0x0f, 0x41, 0x89, 0xa9, 0x77, 0x9e, 0xf4, 0xae,
    0x14, 0x54, 0xfc, 0x05, 0xdd, 0x57, 0x05, 0x4a, 0xba, 0xd7, 0xc4, 0x16, 0xb7, 0x80, 0x03, 0x27,
    0xf7, 0xf2, 0x70, 0x72, 0xe5, 0x32, 0x0f, 0xd1, 0x3b, 0xa6, 0x34, 0x5b, 0x31, 0xff, 0x4b, 0x70,
    0x03, 0x6b, 0x43, 0x91, 0x2c, 0x9f, 0x3f, 0xd2, 0xf8, 0x24, 0xf6, 0x7d, 0xb3, 0x4e, 0x7f, 0x08,
    0x0f, 0xa0, 0x3e, 0xf3, 0xce, 0x66, 0xbd, 0x12, 0x49, 0x6d, 0xcb, 0xa1, 0x4c, 0x37, 0xbf, 0xf3,
    0xb3, 0xbc, 0x8e, 0xac, 0x6b, 0xb9, 0xd9, 0xe6, 0x25, 0xbc, 0xdf, 0x93, 0x6f, 0x9e, 0x7e, 0x07,
    0x00, 0x00, 0xff, 0xff, 0x0c, 0x9f, 0x10, 0xa8, 0x2e, 0x01, 0x00, 0x00,
}

对于meta信息的提取还是很方便的

然而

对于多个文件的生成, 这样做非常的麻烦, 因为这个字段会重复导致编译错误

很多人在论坛里吐槽, 官方给出的解决方法是, 使用protoc一次性传入一个package下的所有的proto直接生成一个go

而不是现在的一个proto一个go

生成代码会自动注册到全局, 并可以方便的查询

以前这个代码需要自己来做, 现在官方提供了支持, 很是方便

然而, 为什么不支持遍历… 残念啊, 又要自己动手了

posted on 2016-01-25 14:23 战魂小筑 阅读(26769) 评论(0)  编辑 收藏 引用 所属分类: 游戏开发技术工具使用及设计Golang

只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理