赞
踩
《一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码》,点击传送门,即可获取!
也有proto3,都可以吧,我最开始接触的是2,就翻译 2 吧。
官网地址:https://developers.google.cn/protocol-buffers/docs/proto,有兴趣的朋友可以自行查阅。
好吧,建议自己打开看,我不全翻译,就看到一些觉得比较重要的我搬过来。
你首先需要在一个 .proto 文件中定义你需要做串行化的数据结构信息。每个ProtocolBuffer信息是一小段逻辑记录,包含一系列的键值对。
消息由至少一个字段组合而成,类似于C语言中的结构。每个字段都有一定的格式。
字段格式:限定修饰符① | 数据类型② | 字段名称③ | = | 字段编码值④ | [字段默认值⑤]
这里有个非常简单的 .proto 文件定义了个人信息:
message Person {
required string name=1;
required int32 id=2;
optional string email=3;
enum PhoneType {
MOBILE=0;
HOME=1;
WORK=2;
}
message PhoneNumber {
required string number=1;
optional PhoneType type=2 [default=HOME];
}
repeated PhoneNumber phone=4;
}
Required: 表示是一个必须字段,必须相对于发送方,在发送消息之前必须设置该字段的值,对于接收方,必须能够识别该字段的意思。发送之前没有设置required字段或者无法识别required字段都会引发编解码异常,导致消息被丢弃。
Optional:表示是一个可选字段,可选对于发送方,在发送消息时,可以有选择性的设置或者不设置该字段的值。对于接收方,如果能够识别可选字段就进行相应的处理,如果无法识别,则忽略该字段,消息中的其它字段正常处理。—因为optional字段的特性,很多接口在升级版本中都把后来添加的字段都统一的设置为optional字段,这样老的版本无需升级程序也可以正常的与新的软件进行通信,只不过新的字段无法识别而已,因为并不是每个节点都需要新的功能,因此可以做到按需升级和平滑过渡。
Repeated:表示该字段可以包含0~N个元素。其特性和optional一样,但是每一次可以包含多个值。可以看作是在传递一个数组的值。
Protobuf定义了一套基本数据类型。几乎都可以映射到C++\Java等语言的基础数据类型.
N 表示打包的字节并不是固定。而是根据数据的大小或者长度。
关于message,类似于C语言中的结构包含另外一个结构作为数据成员一样。
编码值的取值范围为 1~2^32(4294967296)。
不信往上面翻翻看,看看是不是都是数值。
其中 1~15的编码时间和空间效率都是最高的,编码值越大,其编码的时间和空间效率就越低(相对于1-15),当然一般情况下相邻的2个值编码效率的是相同的,除非2个值恰好实在4字节,12字节,20字节等的临界区。比如15和16.
1900~2000编码值为Google protobuf 系统内部保留值,建议不要在自己的项目中使用。
protobuf 还建议把经常要传递的值把其字段编码设置为1-15之间的值。
消息中的字段的编码值无需连续,只要是合法的,并且不能在同一个消息中有字段包含相同的编码值。
当在传递数据时,对于required数据类型,如果用户没有设置值,则使用默认值传递到对端。当接受数据是,对于optional字段,如果没有接收到optional字段,则设置为默认值。
protobuf 接口文件可以像C语言的h文件一样,分离为多个,在需要的时候通过 import导入需要的文件。
虽然可以在单个.proto文件中定义多种消息类型(例如消息,枚举和服务),但当在单个文件中定义大量具有不同依赖性的消息时,也
可能导致依赖性膨胀。建议每个.proto文件包含尽可能少的消息类型。
避免名称冲突,可以给每个文件指定一个package名称,对于C++解析为名称空间。
记得在开头加上这两句:
syntax = “proto3”;
package demo;
枚举的定义和C++相同,但是有一些限制。
枚举值必须大于等于0的整数。
使用分号(;)分隔枚举变量而不是C++语言中的逗号(,)
首先,你要有一个PB文件可以拿去编译,我知道你多半也没有,没事我这里有。
syntax = “proto3”;
package demo;
message Person {
string name = 1;
int32 id = 2;
string email = 3;
enum PhoneType {
MOBILE = 0;
HOME = 1;
WORK = 2;
}
message PhoneNumber {
string number = 1;
PhoneType type = 2;
}
repeated PhoneNumber phone = 4;
}
我下载了好多款,不过主语言是C++,毕竟打开一次不容易。打不开下载目录的小伙伴可以私信我拿。
打开cmd, cd到该目录,protoc.exe的命令行参数格式如下:
protoc --proto_path=IMPORT_PATH --cpp_out=DST_DIR --java_out=DST_DIR --python_out=DST_DIR path/to/file.proto
编译之后就会出现新的文件了。
打开之后太长了,自己去看。我这里提几点。
(1)proto中的package在C++中是namespace;
(2)proto中的message在C++中是class,类里面有各个成员的set/get;基类是google::protobuf::Message。
(3)代码中可以看见C++11中的移动构造和移动赋值函数。
搞技术的人不搞那些弯弯绕的,放码过来吧。
syntax = “proto2”;
package tutorial;
message Person {
optional string name = 1;
optional int32 id = 2;
optional string email = 3;
enum PhoneType {
MOBILE = 0;
HOME = 1;
WORK = 2;
}
message PhoneNumber {
optional string number = 1;
optional PhoneType type = 2 [default = HOME];
}
repeated PhoneNumber phones = 4;
}
message AddressBook {
repeated Person people = 1;
}
#include
#include
#include
#include “person.pb.h”
using namespace std;
// This function fills in a Person message based on user input.
void PromptForAddress(tutorial::Person* person) {
cout << "Enter person ID number: ";
int id;
cin >> id;
person->set_id(id);
cin.ignore(256, ‘\n’);
cout << "Enter name: ";
getline(cin, *person->mutable_name());
cout << "Enter email address (blank for none): ";
string email;
getline(cin, email);
if (!email.empty()) {
person->set_email(email);
}
while (true) {
cout << "Enter a phone number (or leave blank to finish): ";
string number;
getline(cin, number);
if (number.empty()) {
break;
}
tutorial::Person::PhoneNumber* phone_number = person->add_phones();
phone_number->set_number(number);
cout << "Is this a mobile, home, or work phone? ";
string type;
getline(cin, type);
if (type == “mobile”) {
phone_number->set_type(tutorial::Person::MOBILE);
} else if (type == “home”) {
phone_number->set_type(tutorial::Person::HOME);
} else if (type == “work”) {
phone_number->set_type(tutorial::Person::WORK);
} else {
cout << “Unknown phone type. Using default.” << endl;
}
}
}
// Main function: Reads the entire address book from a file,
// adds one person based on user input, then writes it back out to the same
// file.
int main(int argc, char* argv[]) {
// Verify that the version of the library that we linked against is
// compatible with the version of the headers we compiled against.
GOOGLE_PROTOBUF_VERIFY_VERSION;
if (argc != 2) {
cerr << “Usage: " << argv[0] << " ADDRESS_BOOK_FILE” << endl;
return -1;
}
tutorial::AddressBook address_book;
{
// Read the existing address book.
fstream input(argv[1], ios::in | ios::binary);
if (!input) {
cout << argv[1] << “: File not found. Creating a new file.” << endl;
} else if (!address_book.ParseFromIstream(&input)) {
cerr << “Failed to parse address book.” << endl;
return -1;
}
}
// Add an address.
PromptForAddress(address_book.add_people());
{
// Write the new address book back to disk.
fstream output(argv[1], ios::out | ios::trunc | ios::binary);
if (!address_book.SerializeToOstream(&output)) {
cerr << “Failed to write address book.” << endl;
return -1;
}
}
// Optional: Delete all global objects allocated by libprotobuf.
google::protobuf::ShutdownProtobufLibrary();
return 0;
}
这份清华大牛整理的进大厂必备的redis视频、面试题和技术文档
祝大家早日进入大厂,拿到满意的薪资和职级~~~加油!!
感谢大家的支持!!
《一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码》,点击传送门,即可获取!
ess book back to disk.
fstream output(argv[1], ios::out | ios::trunc | ios::binary);
if (!address_book.SerializeToOstream(&output)) {
cerr << “Failed to write address book.” << endl;
return -1;
}
}
// Optional: Delete all global objects allocated by libprotobuf.
google::protobuf::ShutdownProtobufLibrary();
return 0;
}
这份清华大牛整理的进大厂必备的redis视频、面试题和技术文档
祝大家早日进入大厂,拿到满意的薪资和职级~~~加油!!
感谢大家的支持!!
[外链图片转存中…(img-CwIvcoi6-1714739013566)]
《一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码》,点击传送门,即可获取!
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。