目录
1.Any类型
1.说明
- 字段还可以声明为
Any
类型,可以理解为泛型类型- 使⽤时可以在
Any
中存储任意消息类型- 父类是
Message
- 父类是
Any
类型的字段也可以⽤repeated
来修饰
- 使⽤时可以在
Any
类型是Google已经定义好的类型,其中的include
⽬录下查找所有Google已经定义好的.proto
⽂件- 以我的机器为例:
ls /usr/include/google/protobuf
- 以我的机器为例:
2.代码&使用
.proto
文件syntax = "proto3";
package contacts;
import "google/protobuf/any.proto"; // 引⼊ any.proto ⽂件
message Address
{
string home_address = 1;
string unit_address = 2;
}
message PeopleInfo
{
string name = 1;
int32 age = 2;
message Phone
{
string number = 1;
enum PhoneType
{
MP = 0;
TEL = 1;
}
PhoneType type = 2;
}
repeated Phone phone = 3;
google.protobuf.Any data = 4;
}
message Contacts
{
repeated PeopleInfo contacts = 1;
}- 编译生成的CPP代码
// 新⽣成的 Address 类 class Address final : public ::PROTOBUF_NAMESPACE_ID::Message { public: using ::PROTOBUF_NAMESPACE_ID::Message::CopyFrom; void CopyFrom(const Address& from); using ::PROTOBUF_NAMESPACE_ID::Message::MergeFrom; void MergeFrom( const Address& from) { Address::MergeImpl(*this, from); } // string home_address = 1; void clear_home_address(); const std::string& home_address() const; template <typename ArgT0 = const std::string&, typename... ArgT> void set_home_address(ArgT0&& arg0, ArgT... args); std::string* mutable_home_address(); PROTOBUF_NODISCARD std::string* release_home_address(); void set_allocated_home_address(std::string* home_address); // string unit_address = 2; void clear_unit_address(); const std::string& unit_address() const; template <typename ArgT0 = const std::string&, typename... ArgT> void set_unit_address(ArgT0&& arg0, ArgT... args); std::string* mutable_unit_address(); PROTOBUF_NODISCARD std::string* release_unit_address(); void set_allocated_unit_address(std::string* unit_address); }; // 更新的 PeopleInfo 类 class PeopleInfo final : public ::PROTOBUF_NAMESPACE_ID::Message { public: // .google.protobuf.Any data = 4; bool has_data() const; void clear_data(); const ::PROTOBUF_NAMESPACE_ID::Any& data() const; PROTOBUF_NODISCARD ::PROTOBUF_NAMESPACE_ID::Any* release_data(); ::PROTOBUF_NAMESPACE_ID::Any* mutable_data(); void set_allocated_data(::PROTOBUF_NAMESPACE_ID::Any* data); };
- 上述代码中,对于
Any
字段- 设置和获取
- 获取⽅法的⽅法名称与字段命名完全相同
- 设置⽅法可以使⽤
mutable_
⽅法,返回值为Any
类型的指针,这类⽅法会为用户开辟好空间,可以直接对这块空间的内容进⾏修改
- 可以在
Any
字段中存储任意消息类型,这就要涉及到任意消息类型和Any
类型的互转PackFrom()
:将任意消息类型转为Any
类型UnpackTo
:将Any
类型转回之前设置的任意消息类型Is
:用来判断存放的消息类型是否为typename T
- 这部分代码就在 Google写好的⽂件
any.pb.h
中class PROTOBUF_EXPORT Any final : public ::PROTOBUF_NAMESPACE_ID::Message { bool PackFrom(const ::PROTOBUF_NAMESPACE_ID::Message& message) { ... } bool UnpackTo(::PROTOBUF_NAMESPACE_ID::Message* message) const { ... } template<typename T> bool Is() const { return _impl_._any_metadata_.Is<T>(); } };
- 设置和获取
2.oneof类型
1.说明
- 如果消息中有很多可选字段, 并且将来同时只有⼀个字段会被设置
- 那么就可以使⽤
oneof
加强这个⾏为,也能有节约内存的效果
- 那么就可以使⽤
- 注意:
- 可选字段中的字段编号,不能与⾮可选字段的编号冲突
- 不能在
oneof
中使⽤repeated
字段 - 将来在设置
oneof
字段中值时,如果将oneof
中的字段设置多个,那么只会保留最后⼀次设置的成员,之前设置的oneof成员会⾃动清除
2.代码&使用
.proto
文件syntax = "proto3";
package contacts;
import "google/protobuf/any.proto"; // 引⼊ any.proto ⽂件
message Address
{
string home_address = 1;
string unit_address = 2;
}
message PeopleInfo
{
string name = 1;
int32 age = 2;
message Phone
{
string number = 1;
enum PhoneType
{
MP = 0;
TEL = 1;
}
PhoneType type = 2;
}
repeated Phone phone = 3;
google.protobuf.Any data = 4;
// 其他联系⽅式:多选⼀
oneof other_contact
{
string qq = 5;
string weixin = 6;
}
}
message Contacts
{
repeated PeopleInfo contacts = 1;
}- 编译生成的CPP代码
// 更新的 PeopleInfo 类 class PeopleInfo final : public ::PROTOBUF_NAMESPACE_ID::Message { enum OtherContactCase { kQq = 5, kWeixin = 6, OTHER_CONTACT_NOT_SET = 0, }; // string qq = 5; bool has_qq() const; void clear_qq(); const std::string& qq() const; template <typename ArgT0 = const std::string&, typename... ArgT> void set_qq(ArgT0&& arg0, ArgT... args); std::string* mutable_qq(); PROTOBUF_NODISCARD std::string* release_qq(); void set_allocated_qq(std::string* qq); // string weixin = 6; bool has_weixin() const; void clear_weixin(); const std::string& weixin() const; template <typename ArgT0 = const std::string&, typename... ArgT> void set_weixin(ArgT0&& arg0, ArgT... args); std::string* mutable_weixin(); PROTOBUF_NODISCARD std::string* release_weixin(); void set_allocated_weixin(std::string* weixin); void clear_other_contact(); OtherContactCase other_contact_case() const; };
- 上述的代码中,对于
oneof
字段- 会将
oneof
中的多个字段定义为一个枚举类型 - 设置和获取:
- 对
oneof
内的字段进⾏常规的设置和获取即可 - 但要注意只能设置⼀个,如果设置 多个,那么只会保留最后⼀次设置的成员
- 对
- 清空
oneof
字段:clear_
⽅法 - 获取当前设置了哪个字段:
_case
⽅法
- 会将
3.map类型
1.说明
- 语法⽀持创建⼀个关联映射字段,也就是可以使⽤
map
类型去声明字段类型,格式:map<key_type, value_type> map_field = N;
- 注意:
key_type
是除了float
和bytes
类型以外的任意标量类型value_type
可以是任意类型map
字段不可以⽤repeated
修饰- map 中存⼊的元素是⽆序的
2.代码&使用
.proto
文件syntax = "proto3";
package contacts;
import "google/protobuf/any.proto"; // 引⼊ any.proto ⽂件
message Address
{
string home_address = 1;
string unit_address = 2;
}
message PeopleInfo
{
string name = 1;
int32 age = 2;
message Phone
{
string number = 1;
enum PhoneType
{
MP = 0;
TEL = 1;
}
PhoneType type = 2;
}
repeated Phone phone = 3;
google.protobuf.Any data = 4;
// 其他联系⽅式:多选⼀
oneof other_contact
{
string qq = 5;
string weixin = 6;
}
map<string, string> remark = 7;
}
message Contacts
{
repeated PeopleInfo contacts = 1;
}- 编译生成的CPP文件
// 更新的 PeopleInfo 类 class PeopleInfo final : public ::PROTOBUF_NAMESPACE_ID::Message { // map<string, string> remark = 7; int remark_size() const; void clear_remark(); const ::PROTOBUF_NAMESPACE_ID::Map< std::string, std::string >& remark() const; ::PROTOBUF_NAMESPACE_ID::Map< std::string, std::string >* mutable_remark(); };
- 上述的代码中,对于
Map
类型的字段- 清空map:
clear_
⽅法 - 设置和获取:
- 获取⽅法的⽅法名称与字段命名完全相同
- 设置⽅法为
mutable_
⽅法,返回值为Map
类型的指针,这类⽅法会为用户开辟好空间,可以直接对这块空间的0内容进⾏修改
- 清空map: