- 安装
- 数据类型与GO对比
- 消息体
- 数组 repeated
- 枚举 enum
- 联合体 oneof
- 编译protobuf
protobuf-c 编译器
二进制安装
1.下载二进制包
wget https://github.com/protocolbuffers/protobuf/releases/download/v3.17.3/protoc-3.17.3-linux-x86_64.zip
2.解压设置环境变量
unzip protoc-3.17.3-linux-x86_64.zip -d protoc
// shell 环境变量
vim /etc/profile
export PROTOC=~/protoc
export PATH=$PATH:$PROTOC/bin
source /etc/profile
//fish 环境变量
vim ~/.config/fish/config.fish
set -x PROTOC /home/wzl/protoc
set -x PATH $PROTOC/bin $PATH
sudo vim /etc/fish/config.fish
source /etc/fish/config.fish
3.测试命令提示
安装protobuf-go
git clone https://github.com/golang/protobuf.git
mv protobuf $GOMODCACHE/github.com/golang/
cd $GOMODCACHE/github.com/golang/protobuf/protoc-gen-go
go build
sudo cp protoc-gen-go /bin
//有自动提示安装成功
数据类型与GO对比
- .proto | GO
double | float64
float | float32
int32 | int32
int64 | int64
uint32 | uint32
uint64 | uint64
sint32 | int32
sint64 | int64
fixed64 | uint32
fixed64 | uint64
bool | bool
string | string
bytes | []byte
消息体
1.定义消息体
//默认是proto2
syntax="proto3";
//指定所在包名
package pb;
//定义消息体
message Person {
string name = 1;//字段编号,可不从1开始,但不能重复
int32 age = 2;
}
2.消息体嵌套
syntax="proto3";
package pb;
message Person {
string name = 1;
int32 age = 2;
PhoneNumber p = 3; //消息体可嵌套
}
message PhoneNumber {
string number = 1;
int64 type = 2;
}
3.字段编号
1)每个字段唯一编号
2)范围:1 - 536870911,其中19000~19999是协议缓冲区保留数
数组 repeated
repeadted关键字类似与go中的切片,编译之后对应的也是go的切片:
syntax="proto3";
package pb;
message Person {
string name = 1;
int32 age = 2;
message PhoneNumber {
string number = 1;
int64 type = 2;
}
repeated PhoneNumber phone = 3; //数组
}
枚举 enum
syntax="proto3";
package pb;
//定义枚举类型
enum Week {
Monday = 0; //枚举值,必须从0开始,与写入编号无关
Turesday =1;
}
message Person {
string name = 1;
int32 age = 2;
//枚举
Week w = 5;
}
联合体 oneof
syntax="proto3";
package pb;
message Person {
string name = 1;
int32 age = 2;
//联合体
oneof data {
string teacher = 3; //写入编号不能重复
string class = 4;
}
}
编译protobuf
go编译命令
protoc --go_out=./ *.proto ---> xxx.pb.go
c++编译命令
protoc --cpp_out=./ *.proto ---> xxx.pb.cc,xxx.pb.h
编译错误
protoc-gen-go: unable to determine Go import path for "test.proto"
Please specify either:
? a "go_package" option in the .proto source file, or
? a "M" argument on the command line.
- 修改错误
文件中添加 option go_package = "path/packageName";
// 或 "../pb;pb" 路径;包名
syntax="proto3";
package pb;
option go_package = "./pb"; //生成包路径
message Person {
string name = 1;
int32 age = 2;
PhoneNumber p = 3; //消息体可嵌套
}
message PhoneNumber {
string number = 1;
int64 type = 2;
}
添加rpc服务
- 语法
service 服务名 {
rpc 函数名(参数:消息体) returns (返回值:消息体)
}
例
message People {
string name = 1;
}
message Man {
int32 age = 2;
}
service hello {
rpc HelloPeple(People) returns (Man);
}
- 编译期间,protobuf默认不编译服务,要想使之编译。需要使用gRPC.
- 编译指令
protoc --go_out=plugins=grpc:./ *.proto
序列化
package main
import (
"ImTransfer/pb"
"fmt"
"google.golang.org/protobuf/proto"
)
func main() {
req := pb.PhoneNumber{
Number: "123",
Type: 11,
}
rsp, _ := proto.Marshal(&req)
fmt.Println(string(rsp))
}
反序列化
import (
"ImTransfer/pb"
"fmt"
"google.golang.org/protobuf/proto"
)
func main() {
req := pb.PhoneNumber{
Number: "123",
Type: 11,
}
rsp, _ := proto.Marshal(&req)
fmt.Println(string(rsp))
//反序列化
newReq := new(pb.PhoneNumber)
_ = proto.Unmarshal(rsp, newReq)
fmt.Println(newReq)
}