闲话一下
- 最近打算做一个联网的小游戏,通讯协议决定使用protobuf,之前的工作环境都是在linx下进行开发的,这次我打算从零开始,在windows系统下开发,而这篇文件也主要介绍我如何配置gogoprotobuf的环境,以及期间遇到的问题。不是protobuf么,为何变为gogoprotobuf?因为网上查了下资料,发现gogoprotobuf生成速度比protobuf还要快一些,既然如此为何不用更好的。
准备工作
首先你需要在github上下载github.com/gogo/protobuf和github.com/Knetic/govaluate,没翻墙?下载速度1kb/s?我已经给你们准备好了,之前我下了3个小时,放在我的网盘地址上了(挂了请留言)。
然后你需要一个编译好了的protoc的可执行文件,你可以在github.com/protocolbuffers/protobuf下载源码,然后在本机上编译。也可以直接从官网下载已经生成好了的可执行文件,地址如下github.com/google/protobuf/releases。我这边生成发现少了好多依赖包,节约时间,就自己下了个windows的64位的文件。也放在网盘上的。
网盘地址:https://pan.baidu.com/s/1lnv5F3IFcTcGQBa1nqgijQ
提取码:hi4d
创建你的工程目录
你下载的github.com文件夹拷贝到src目录下,并在src目录下创建一个test文件夹,我的test是我的项目名字,等会我会把proto文件放在这个目录下。
接下来你要编译gogo的protoc-gen-go文件,进入github.com\gogo\protobuf\protoc-gen-gogofast和github.com\gogo\protobuf\protoc-gen-gogo(这里我就选用了这2个),使用go
build命令生成可执行文件。并将生成的文件和protoc.exe一起放入bin目录下。
接下来在我们的test文件夹里创建一个proto文件,并附上内容
syntax = "proto3";
package gameMsg;
import "github.com/gogo/protobuf/gogoproto/gogo.proto";
//option (gogoproto.goproto_sizecache_all) = false;
//option (gogoproto.goproto_unkeyed_all) = false;
//option (gogoproto.goproto_unrecognized_all) = false;
enum TestPid {
cInvalid = 0; //无效的消息id
cLogin = 1000; //登陆请求
cLogout = 1001; //登出请求
}
//协议头
message PbTest {
option (gogoproto.goproto_getters) = false;
string PlayerId = 1; //用户id
string Sign = 2; //签名
int32 Tick = 3; //时间戳(秒)
}
生成go文件
如果你对生成的go的格式没有什么要求,把上面的引用gogo.proto注释掉,执行下面的命令就应该行了。而作为有强迫症的我,就只有默默的踩坑。
%GOPATH%\bin\protoc.exe --plugin=protoc-gen-go=%GOPATH%\bin\protoc-gen-gogo.exe --go_out=. base.proto(%GOPATH%你们这个需要自己在环境变量里面改,我这里的是E\gotest,protoc-gen-gogo.exe就是刚才我们生成的文件)
然后报错,具体就是说缺少google/protobuf/descriptor.proto文件,我在目录下一看,确实没这个包,咋办呢?我突然想到了之前gogoproto介绍说兼容了google的proto,那么肯定本地应该有这个文件的,果然不出我的猜想,在github.com\gogo\protobuf\protobuf目录下发现了google文件夹,然后顺腾摸瓜就找到了descriptor.proto文件。
于是我们就改下这个gogo.proto中descriptor.proto的地址吧,在改之前最好拷贝一份,做个备份,万一你的git回滚不了呢
这次我们再试一试,生成go文件成功,这下我们就可以使用这个gameMsg了
我们还想要更简洁的代码
上面的代码被我标注红色的可以看出,这些东西看着是不是很别扭,因为对我而言,我根本用不着这些,我解析都有自己的一套规则,还有加密算法在里面,所以我只需要生成这个结构体部分就行了,多余的部分那就想办法干掉它。
于是通过网上查询,找到了一些取消这个字段的方法,具体不多讲,百度能查到各个字段的意思,有兴趣的朋友可以查查。 option
(gogoproto.goproto_sizecache_all) = false; option
(gogoproto.goproto_unkeyed_all) = false; option
(gogoproto.goproto_unrecognized_all) = false;然后我们看到的效果是果然xxx的字段没有了,但是下面的函数带xxx的还有。
我有时候都怀疑我是金牛座的——犟,查了大量网上资料无果后,咋办?看源码吧,找到它,接近它,干掉它(就是这么暴力)。
最后在github.com/gogo/protobuf/protoc-gen-gogo/generator里找到了XXX_Unmarshal,它是在generateCommonMethods函数里,大致看了一下,这里就是它自动给你生成函数的地方,查看调用的地方,注释了没啥影响,注释掉。
然后重新编译下protoc-gen-gogo.exe吧,编译好了记得替换掉bin目录下的protoc-gen-gogo.exe
然后执行,看看结果,果然不见了,现在是不是看着清爽多了,当然你如果还是想用工具里自带的序列化和反序列化,那你还是保留吧。
总结
工具这东西就是为了让我们使用方便的东西,如果当使用费劲的时候,我们就应该想如何去解决问题,把复杂的东西简单化,提高效率才是我们所不断追求的目标。希望这篇文章能带给那些需要人一些帮助。