protobuf

  • 安装
  • 数据类型与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
protobuf
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

安装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
//有自动提示安装成功

protobuf

数据类型与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))
}

protobuf

反序列化

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)
}

protobuf

protobuf

上一篇:解决中文在 html 文件中乱码


下一篇:实验1:SDN拓扑实践