翻V围P栏N查看: Language Guide (proto3)
1.protobuf是什么?
protobuf是google旗下的一款平台无关,语言无关,可扩展的序列化结构数据格式。所以很适合用做数据存储和作为不同应用,不同语言之间相互通信的数据交换格式,只要实现相同的协议格式即同一 proto文件被编译成不同的语言版本,加入到各自的工程中去。这样不同语言就可以解析其他语言通过 protobuf序列化的数据。
2.数据交互xml、json、protobuf格式比较
(1)json: 一般的web项目中,最流行的主要还是json。因为浏览器对于json数据支持非常好,有很多内建的函数支持。
(2)xml: 在webservice中应用最为广泛,但是相比于json,它的数据更加冗余,因为需要成对的闭合标签。json使用了键值对的方式,不仅压缩了一定的数据空间,同时也具有可读性。
(3)protobuf:是谷歌开源的一种数据格式,适合高性能,对响应速度有要求的数据传输场景。因为profobuf是二进制数据格式,需要编码和解码。数据本身不具有可读性。因此只能反序列化之后得到真正可读的数据。
3.相对于其它protobuf更具有优势
(1) 序列化后体积相比Json和XML很小,适合网络传输
(2) 支持跨平台多语言
(3) 消息格式升级和兼容性还不错
(4) 序列化反序列化速度很快,快于Json的处理速速
4.protobuf安装
(1)下载 protobuf安装包
$ git clone https://github.com/protocolbuffers/protobuf.git
(2)安装依赖库
$ sudo apt-get install autoconf automake libtool curl make g++ unzip libffi-dev -y
(3)安装
$ cd protobuf/
$ ./autogen.sh
$ ./configure
$ make
$ sudo make install
$ sudo ldconfig // 刷新共享库,很重要的一步
(4)测试一下是否安装成功
$ protoc –h
(5)获取 proto包(Go语言的proto API接口)
$ go get -v -u github.com/golang/protobuf/proto
(6)进入GOPATH/src/github.com/golang/protobuf/protoc-gen-go目录下,打开终端,输入:
$ go build
(7)将build生成的protoc-gen-go可执行文件复制到/bin目录下
$ sudo cp protoc-gen-go /bin/
5.protobuf的语法
写一个简单的example..proto文件,如下:
文件的第一行指定了你正在使用proto3语法:如果你没有指定这个,编译器会使用proto2。这个指定语法行必须是文件的非空非注释的第一个行。
在上面的例子中,所有字段都是标量类型:两个整型(height和weight),一个string类型(name)。Repeated 关键字表示重复,那么在go语言中用切片进行代表。
对go来说,编译器会为每个消息类型生成了一个.pd.go文件。可以通过定义好的.proto文件来生成Java,Python,C++, Ruby, JavaNano, Objective-C,或者C# 代码,需要基于.proto文件运行protocol buffer编译器protoc。
通过如下方式调用protocol编译器:
如下,进入example.proto文件同一目录下,输入protoc –go_out=./ *.proto ,就会在当前目录下生成一个example.pb.go文件:
接下来,我们打开example.pb.go文件,看看里面的内容:
6.protobuf的golang调用测试
(1)在protobuf目录下再创建一个test1目录,进入test1目录下,创建一个test1.proto文件,内容如下:
(2)调用protocol编译器,输入protoc –go_out=./ *.proto ,生成test1.pb.go文件:
(3)在protobuf目录下再创建一个go-test1目录,进入go-test1目录下,创建一个test1.go文件,内容如下:
package main import ( "fmt" "github.com/golang/protobuf/proto" "protobuf/test1" ) func main() { test := &protobuf.Test{ Name:"sxf", Weight:[]int32{120,144,200,170,140}, Height:180, Motto:"鸡你太美", } fmt.Println(test) data,err := proto.Marshal(test) //proto编码 if err != nil{ fmt.Println("编码失败") } fmt.Println(data) //编码后打印 //proto的解码 newtest := &protobuf.Test{} err = proto.Unmarshal(data,newtest) if err != nil{ fmt.Println("解码失败") } fmt.Println(newtest) //解码后打印 fmt.Println(newtest.String()) //转成字符串 fmt.Println("名字:",newtest.Name) fmt.Println("体重的变化:",newtest.Weight) fmt.Println("身高:",newtest.Height) fmt.Println("格言:",newtest.Motto) }
(4)运行test1.go,查看运行结果: