Google Protocol Buffer (简称 Protobuf)是google旗下的一款轻便高效的结构化数据存储格式
相比于json和xml:
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/
4、自动生成configure配置文件:
./autogen.sh
5、配置环境:
./configure
6、编译源代码(时间比较长):
make
7、安装
sudo make install
8、刷新共享库
sudo ldconfig
9、成功后需要使用命令测试
protoc -h
1.获取go语言的proto包 API接口
go get -v -u github.com/golang/protobuf/proto
go get -v -u github.com/golang/protobuf/protoc-gen-go
2.编译
cd $GOPATH/src/github.com/golang/protobuf/protoc-gen-go/
go build
3.将生成的protoc-gen-go可执行文件,放到/bin目录下
sudo cp protoc-gen-go /bin/
protobuf 通常会把用户定义的结构体类型叫做一个消息,写在一个以 .proto 结尾的文件中.
消息格式:
(字段修饰符)数据类型 字段名称 = 唯一的编号标签值;
- 字段修饰符-例如: repeated…
- 字段名称: protobuf建议以下划线命名而非驼峰式
- 唯一的编号标签: 在同一个消息里不可以重复
- 注释格式: 使用//,但是不要写在代码右侧,编译后会消失
//版本号
syntax = "proto3" ;
//包名
package pb ;
//消息体
message Person{
string name = 1 ;
int32 age = 3 ;
//repeated是重复的,类似go中的切片
repeated string emails = 4 ;
//Phone_number 变量类型
repeated Phone_number phones = 5 ;
}
//Phone_number 是消息体名
message Phone_number {
string number = 1;
int64 type = 2;
}
//enum 是枚举类型的关键字
//Phone_type 枚举名称
enum Phone_type{
//后面的数值并不是序列 而是枚举的编号 一般是从0开始
Mobile = 0 ;
Home = 1 ;
Work = 2 ;
}
数据类型
.proto类型 | Go类型 | 介绍 |
---|---|---|
double | float64 | 64位浮点数 |
float | float32 | 32位浮点数 |
int32 | int32 | 使用可变长度编码。编码负数效率低下——如果你的字段可能有负值,请改用sint32。 |
int64 | int64 | 使用可变长度编码。编码负数效率低下——如果你的字段可能有负值,请改用sint64。 |
uint32 | uint32 | 使用可变长度编码。 |
uint64 | uint64 | 使用可变长度编码。 |
sint32 | int32 | 使用可变长度编码。符号整型值。这些比常规int32s编码负数更有效。 |
sint64 | int64 | 使用可变长度编码。符号整型值。这些比常规int64s编码负数更有效。 |
fixed32 | uint32 | 总是四字节。如果值通常大于228,则比uint 32更有效 |
fixed64 | uint64 | 总是八字节。如果值通常大于256,则比uint64更有效 |
sfixed32 | int32 | 总是四字节。 |
sfixed64 | int64 | 总是八字节。 |
bool | bool | 布尔类型 |
string | string | 字符串必须始终包含UTF - 8编码或7位ASCII文本 |
bytes | []byte | 可以包含任意字节序列 |
可以通过定义好的.proto文件来生成go格式的代码
protoc --proto_path=IMPORT_PATH --go_out=DST_DIR path/to/file.proto
protoc [OPTION] PROTO_FILES
–proto_path=IMPORT_PATH //IMPORT_PATH指定了 .proto 文件导包时的路径,如果忽略则默认当前目录。如果有多个目录则可以多次调用–proto_path,它们将会顺序的被访问并执行导入。
–go_out=DST_DIR //指定生成的go语言代码文件放入的文件夹
注意:
允许使用 protoc --go_out=./ *.proto
的方式一次性编译多个 .proto 文件
编译时,protobuf 编译器会把 .proto 文件编译成 .pd.go 文件
protoc --go_out=./ *.proto
这时文件夹中生成一个194行代码的person.pb.go文件.
package main
import (
"fmt"
"github.com/golang/protobuf/proto"
"github.com/12-testProto" //注意这个是包含person.pb.go文件的包
)
func main() {
person := &pb.Person{
Name:"tom",
Age:18,
Emails:[]string{"[email protected]"},
Phones:[]*pb.PhoneNumber{
&pb.PhoneNumber{
Number:"12312341234",
Type: int64(pb.PhoneType_Work),
},
&pb.PhoneNumber{
Number:"32143214321",
Type:int64(pb.PhoneType_Home),
},
},
}
fmt.Println("第一次打印",person)
//进行序列化
data,err :=proto.Marshal(person)
if err !=nil{
fmt.Println("proto序列化失敗",err)
}
fmt.Println("第二次打印",string (data))
//反序列化
newdata :=&pb.Person{}
err =proto.Unmarshal(data,newdata)
if err !=nil{
fmt.Println("proto反序列化失敗",err)
}
fmt.Println("第三次打印",newdata)
fmt.Println("姓名",newdata.Name)
}
Output:
第一次打印 name:"tom" age:18 emails:"[email protected]" phones:<number:"12312341234" type:2 > phones:<number:"32143214321" type:1 >
第二次打印
tom"123456@163.␌⎺└*
12312341234*
32143214321
第三次打印 name:"tom" age:18 emails:"123456@163.com" phones:12312341234" type:2 > phones:32143214321" type:1 >
姓名 tom