[Protobuf] 快速上手:安全高效的序列化指南

标题:[Protobuf] (1)快速上手
@水墨不写bug


在这里插入图片描述


文章目录

  • 一、什么是protobuf?
  • 二、protobuf的特点
  • 三、使用protobuf的过程?
    • 1、定义消息格式(.proto文件)
      • (1)指定语法版本
      • (2)package 声明符
    • 2、使用protoc编译器生成代码
      • (1)当前目录直接编译:
      • (2)指定目录编译
    • 3、在业务中引入并使用生成的类
    • 4、在网络通信或存储中使用protobuf序列化数据
  • 四、快速上手写一个小需求来熟悉如何编写proto文件?


一、什么是protobuf?

Protocol Buffers(简称 protobuf)是由 Google 开发的一种与语言无关、平台无关、可扩展序列化数据结构的方法。它用于结构化数据的序列化与反序列化,类似于 XMLJSON,但更小、更快、更简单


二、protobuf的特点

protobuf 可以把数据结构(比如对象或消息)编码成紧凑的二进制格式,之后再还原回原始的数据结构。 这说明protobuf编码是比较安全的,因为二进制无法被直接阅读。

其他重要特点:

  • 跨语言(支持 Java、C++、Python、Go、C#、JavaScript 等多种语言)
  • 二进制格式,高效且体积小
  • 向后兼容和向前兼容性好(适合长期演进的系统)
  • 需要提前定义数据结构(.proto 文件)

减少开发周期和负担
protobuf可以通过protoc编译器来编译proto文件来生成对应的头文件和源文件,内部已经实现了序列化和反序列化的接口。- - - 节省开发时间,避免重复性造轮子


三、使用protobuf的过程?

1、定义消息格式(.proto文件)

(1)指定语法版本

创建**.proto**文件后,首行需要先指定protobuf的语法版本,如果不指定,默认使用proto2。一般我们都使用proto3。 - - - proto3的语法更加简便,支持更多的语言(比如C#)

(2)package 声明符

在proto文件编译之后,如果写了pageage声明,那么cc和h文件内部会被命名空间封装。
如果没有package声明,则cc和h文件的对应类不会被命名空间包裹。

2、使用protoc编译器生成代码

经过1、2两步,后,就可以编写消息的内部数据结构了,假如如下设计(文件名称为 “contact.proto” ):

//首行:语法指定行
syntax = "proto3";//package 声明符
package contast;//定义联系人信息
message PersonInfo
{string name = 1;int32 age = 2;
}

下一步就需要编译:

(1)当前目录直接编译:

protoc --cpp_out=. contact.proto

这段指令的含义如下:

  • protoc:表示 Protocol Buffers 的编译器程序(Protocol Compiler)。
  • --cpp_out=.:指定生成 C++ 语言的代码文件,并将生成的文件输出到当前目录(. 代表当前目录)。
  • contact.proto:需要被编译的 proto 文件,即你定义了消息结构的协议文件。

综合解释
这条命令的作用是:
使用 Protocol Buffers 的编译器 protoc,将 contact.proto 文件中定义的消息结构,自动生成对应的 C++ 源代码文件(通常为 contact.pb.hcontact.pb.cc),并把它们输出到当前目录下。

这样你就可以在 C++ 项目中直接包含和使用这些自动生成的代码了。

(2)指定目录编译

这种情况适用于当前没有处在contact.proto文件所在的目录时:

protoc -I contact_dir/ --cpp_out=contact_dir/ contact.proto

这段指令的含义如下:

  • protoc
    Protocol Buffers 的编译器(protocol compiler)。

  • -I contact_dir/
    指定包含 proto 文件的搜索目录(即 import 路径)。表示编译器在 contact_dir/ 目录下查找 proto 文件及其 import 的依赖。

  • --cpp_out=contact_dir/
    指定输出目录contact_dir/,并生成 C++ 源代码(通常为 .pb.h.pb.cc 文件)。

  • contact.proto
    要编译的 proto 文件,定义了具体的数据结构。


综合解释:
这条命令会让 protoccontact_dir/ 目录下查找 contact.proto,将其编译为 C++ 源代码,并把生成的 .pb.h.pb.cc 文件输出到同样的 contact_dir/ 目录下。

这种写法常用于项目结构较复杂时,便于管理 proto 文件及生成的代码。


3、在业务中引入并使用生成的类

通过protoc编译proto文件之后,会生成下面两个文件:

// Generated by the protocol buffer compiler.  DO NOT EDIT!
// NO CHECKED-IN PROTOBUF GENCODE
// source: contact.proto
// Protobuf C++ Version: 6.31.0#include "contact.pb.h"#include <algorithm>
#include <type_traits>
#include "google/protobuf/io/coded_stream.h"
#include "google/protobuf/generated_message_tctable_impl.h"
#include "google/protobuf/extension_set.h"
#include "google/protobuf/generated_message_util.h"
#include "google/protobuf/wire_format_lite.h"
#include "google/protobuf/descriptor.h"
#include "google/protobuf/generated_message_reflection.h"
#include "google/protobuf/reflection_ops.h"
#include "google/protobuf/wire_format.h"
// @@protoc_insertion_point(includes)// Must be included last.
#include "google/protobuf/port_def.inc"
PROTOBUF_PRAGMA_INIT_SEG
namespace _pb = ::google::protobuf;
namespace _pbi = ::google::protobuf::internal;
namespace _fl = ::google::protobuf::internal::field_layout;
namespace contact {inline constexpr Info::Impl_::Impl_(::_pbi::ConstantInitialized) noexcept: _cached_size_{0},name_(&::google::protobuf::internal::fixed_address_empty_string,::_pbi::ConstantInitialized()),age_{0} {}template <typename>
PROTOBUF_CONSTEXPR Info::Info(::_pbi::ConstantInitialized)
#if defined(PROTOBUF_CUSTOM_VTABLE): ::google::protobuf::Message(Info_class_data_.base()),
#else   // PROTOBUF_CUSTOM_VTABLE: ::google::protobuf::Message(),
#endif  // PROTOBUF_CUSTOM_VTABLE_impl_(::_pbi::ConstantInitialized()) {
}
struct InfoDefaultTypeInternal {PROTOBUF_CONSTEXPR InfoDefaultTypeInternal() : _instance(::_pbi::ConstantInitialized{}) {}~InfoDefaultTypeInternal() {}union {Info _instance;};
};PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINITPROTOBUF_ATTRIBUTE_INIT_PRIORITY1 InfoDefaultTypeInternal _Info_default_instance_;
}  // namespace contact
static constexpr const ::_pb::EnumDescriptor *PROTOBUF_NONNULL *PROTOBUF_NULLABLEfile_level_enum_descriptors_contact_2eproto = nullptr;
static constexpr const ::_pb::ServiceDescriptor *PROTOBUF_NONNULL *PROTOBUF_NULLABLEfile_level_service_descriptors_contact_2eproto = nullptr;
const ::uint32_tTableStruct_contact_2eproto::offsets[] ABSL_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = {0x081, // bitmapPROTOBUF_FIELD_OFFSET(::contact::Info, _impl_._has_bits_),5, // hasbit index offsetPROTOBUF_FIELD_OFFSET(::contact::Info, _impl_.name_),PROTOBUF_FIELD_OFFSET(::contact::Info, _impl_.age_),0,1,
};static const ::_pbi::MigrationSchemaschemas[] ABSL_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = {{0, sizeof(::contact::Info)},
};
static const ::_pb::Message* PROTOBUF_NONNULL const file_default_instances[] = {&::contact::_Info_default_instance_._instance,
};
const char descriptor_table_protodef_contact_2eproto[] ABSL_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = {"\n\rcontact.proto\022\007contact\"!\n\004Info\022\014\n\004name""\030\001 \001(\t\022\013\n\003age\030\002 \001(\005b\006proto3"
};
static ::absl::once_flag descriptor_table_contact_2eproto_once;
PROTOBUF_CONSTINIT const ::_pbi::DescriptorTable descriptor_table_contact_2eproto = {false,false,67,descriptor_table_protodef_contact_2eproto,"contact.proto",&descriptor_table_contact_2eproto_once,nullptr,0,1,schemas,file_default_instances,TableStruct_contact_2eproto::offsets,file_level_enum_descriptors_contact_2eproto,file_level_service_descriptors_contact_2eproto,
};
namespace contact {
// ===================================================================class Info::_Internal {public:using HasBits =decltype(::std::declval<Info>()._impl_._has_bits_);static constexpr ::int32_t kHasBitsOffset =8 * PROTOBUF_FIELD_OFFSET(Info, _impl_._has_bits_);
};Info::Info(::google::protobuf::Arena* PROTOBUF_NULLABLE arena)
#if defined(PROTOBUF_CUSTOM_VTABLE): ::google::protobuf::Message(arena, Info_class_data_.base()) {
#else   // PROTOBUF_CUSTOM_VTABLE: ::google::protobuf::Message(arena) {
#endif  // PROTOBUF_CUSTOM_VTABLESharedCtor(arena);// @@protoc_insertion_point(arena_constructor:contact.Info)
}
PROTOBUF_NDEBUG_INLINE Info::Impl_::Impl_(::google::protobuf::internal::InternalVisibility visibility,::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const Impl_& from,const ::contact::Info& from_msg): _has_bits_{from._has_bits_},_cached_size_{0},name_(arena, from.name_) {}Info::Info(::google::protobuf::Arena* PROTOBUF_NULLABLE arena,const Info& from)
#if defined(PROTOBUF_CUSTOM_VTABLE): ::google::protobuf::Message(arena, Info_class_data_.base()) {
#else   // PROTOBUF_CUSTOM_VTABLE: ::google::protobuf::Message(arena) {
#endif  // PROTOBUF_CUSTOM_VTABLEInfo* const _this = this;(void)_this;_internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>(from._internal_metadata_);new (&_impl_) Impl_(internal_visibility(), arena, from._impl_, from);_impl_.age_ = from._impl_.age_;// @@protoc_insertion_point(copy_constructor:contact.Info)
}
PROTOBUF_NDEBUG_INLINE Info::Impl_::Impl_(::google::protobuf::internal::InternalVisibility visibility,::google::protobuf::Arena* PROTOBUF_NULLABLE arena): _cached_size_{0},name_(arena) {}inline void Info::SharedCtor(::_pb::Arena* PROTOBUF_NULLABLE arena) {new (&_impl_) Impl_(internal_visibility(), arena);_impl_.age_ = {};
}
Info::~Info() {// @@protoc_insertion_point(destructor:contact.Info)SharedDtor(*this);
}
inline void Info::SharedDtor(MessageLite& self) {Info& this_ = static_cast<Info&>(self);this_._internal_metadata_.Delete<::google::protobuf::UnknownFieldSet>();ABSL_DCHECK(this_.GetArena() == nullptr);this_._impl_.name_.Destroy();this_._impl_.~Impl_();
}inline void* PROTOBUF_NONNULL Info::PlacementNew_(const void* PROTOBUF_NONNULL, void* PROTOBUF_NONNULL mem,::google::protobuf::Arena* PROTOBUF_NULLABLE arena) {return ::new (mem) Info(arena);
}
constexpr auto Info::InternalNewImpl_() {return ::google::protobuf::internal::MessageCreator::CopyInit(sizeof(Info),alignof(Info));
}
constexpr auto Info::InternalGenerateClassData_() {return ::google::protobuf::internal::ClassDataFull{::google::protobuf::internal::ClassData{&_Info_default_instance_._instance,&_table_.header,nullptr,  // OnDemandRegisterArenaDtornullptr,  // IsInitialized&Info::MergeImpl,::google::protobuf::Message::GetNewImpl<Info>(),
#if defined(PROTOBUF_CUSTOM_VTABLE)&Info::SharedDtor,::google::protobuf::Message::GetClearImpl<Info>(), &Info::ByteSizeLong,&Info::_InternalSerialize,
#endif  // PROTOBUF_CUSTOM_VTABLEPROTOBUF_FIELD_OFFSET(Info, _impl_._cached_size_),false,},&Info::kDescriptorMethods,&descriptor_table_contact_2eproto,nullptr,  // tracker};
}PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 const::google::protobuf::internal::ClassDataFull Info_class_data_ =Info::InternalGenerateClassData_();PROTOBUF_ATTRIBUTE_WEAK const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL
Info::GetClassData() const {::google::protobuf::internal::PrefetchToLocalCache(&Info_class_data_);::google::protobuf::internal::PrefetchToLocalCache(Info_class_data_.tc_table);return Info_class_data_.base();
}
PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_INIT_PRIORITY1
const ::_pbi::TcParseTable<1, 2, 0, 25, 2>
Info::_table_ = {{PROTOBUF_FIELD_OFFSET(Info, _impl_._has_bits_),0, // no _extensions_2, 8,  // max_field_number, fast_idx_maskoffsetof(decltype(_table_), field_lookup_table),4294967292,  // skipmapoffsetof(decltype(_table_), field_entries),2,  // num_field_entries0,  // num_aux_entriesoffsetof(decltype(_table_), field_names),  // no aux_entriesInfo_class_data_.base(),nullptr,  // post_loop_handler::_pbi::TcParser::GenericFallback,  // fallback#ifdef PROTOBUF_PREFETCH_PARSE_TABLE::_pbi::TcParser::GetTable<::contact::Info>(),  // to_prefetch#endif  // PROTOBUF_PREFETCH_PARSE_TABLE}, {{// int32 age = 2;{::_pbi::TcParser::SingularVarintNoZag1<::uint32_t, offsetof(Info, _impl_.age_), 1>(),{16, 1, 0, PROTOBUF_FIELD_OFFSET(Info, _impl_.age_)}},// string name = 1;{::_pbi::TcParser::FastUS1,{10, 0, 0, PROTOBUF_FIELD_OFFSET(Info, _impl_.name_)}},}}, {{65535, 65535}}, {{// string name = 1;{PROTOBUF_FIELD_OFFSET(Info, _impl_.name_), _Internal::kHasBitsOffset + 0, 0,(0 | ::_fl::kFcOptional | ::_fl::kUtf8String | ::_fl::kRepAString)},// int32 age = 2;{PROTOBUF_FIELD_OFFSET(Info, _impl_.age_), _Internal::kHasBitsOffset + 1, 0,(0 | ::_fl::kFcOptional | ::_fl::kInt32)},}},// no aux_entries{{"\14\4\0\0\0\0\0\0""contact.Info""name"}},
};
PROTOBUF_NOINLINE void Info::Clear() {
// @@protoc_insertion_point(message_clear_start:contact.Info)::google::protobuf::internal::TSanWrite(&_impl_);::uint32_t cached_has_bits = 0;// Prevent compiler warnings about cached_has_bits being unused(void) cached_has_bits;cached_has_bits = _impl_._has_bits_[0];if ((cached_has_bits & 0x00000001u) != 0) {_impl_.name_.ClearNonDefaultToEmpty();}_impl_.age_ = 0;_impl_._has_bits_.Clear();_internal_metadata_.Clear<::google::protobuf::UnknownFieldSet>();
}#if defined(PROTOBUF_CUSTOM_VTABLE)
::uint8_t* PROTOBUF_NONNULL Info::_InternalSerialize(const ::google::protobuf::MessageLite& base, ::uint8_t* PROTOBUF_NONNULL target,::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) {const Info& this_ = static_cast<const Info&>(base);
#else   // PROTOBUF_CUSTOM_VTABLE
::uint8_t* PROTOBUF_NONNULL Info::_InternalSerialize(::uint8_t* PROTOBUF_NONNULL target,::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) const {const Info& this_ = *this;
#endif  // PROTOBUF_CUSTOM_VTABLE// @@protoc_insertion_point(serialize_to_array_start:contact.Info)::uint32_t cached_has_bits = 0;(void)cached_has_bits;// string name = 1;if ((this_._impl_._has_bits_[0] & 0x00000001u) != 0) {if (!this_._internal_name().empty()) {const ::std::string& _s = this_._internal_name();::google::protobuf::internal::WireFormatLite::VerifyUtf8String(_s.data(), static_cast<int>(_s.length()), ::google::protobuf::internal::WireFormatLite::SERIALIZE, "contact.Info.name");target = stream->WriteStringMaybeAliased(1, _s, target);}}// int32 age = 2;if ((this_._impl_._has_bits_[0] & 0x00000002u) != 0) {if (this_._internal_age() != 0) {target =::google::protobuf::internal::WireFormatLite::WriteInt32ToArrayWithField<2>(stream, this_._internal_age(), target);}}if (ABSL_PREDICT_FALSE(this_._internal_metadata_.have_unknown_fields())) {target =::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray(this_._internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance), target, stream);}// @@protoc_insertion_point(serialize_to_array_end:contact.Info)return target;
}#if defined(PROTOBUF_CUSTOM_VTABLE)
::size_t Info::ByteSizeLong(const MessageLite& base) {const Info& this_ = static_cast<const Info&>(base);
#else   // PROTOBUF_CUSTOM_VTABLE
::size_t Info::ByteSizeLong() const {const Info& this_ = *this;
#endif  // PROTOBUF_CUSTOM_VTABLE// @@protoc_insertion_point(message_byte_size_start:contact.Info)::size_t total_size = 0;::uint32_t cached_has_bits = 0;// Prevent compiler warnings about cached_has_bits being unused(void)cached_has_bits;::_pbi::Prefetch5LinesFrom7Lines(&this_);cached_has_bits = this_._impl_._has_bits_[0];if ((cached_has_bits & 0x00000003u) != 0) {// string name = 1;if ((cached_has_bits & 0x00000001u) != 0) {if (!this_._internal_name().empty()) {total_size += 1 + ::google::protobuf::internal::WireFormatLite::StringSize(this_._internal_name());}}// int32 age = 2;if ((cached_has_bits & 0x00000002u) != 0) {if (this_._internal_age() != 0) {total_size += ::_pbi::WireFormatLite::Int32SizePlusOne(this_._internal_age());}}}return this_.MaybeComputeUnknownFieldsSize(total_size,&this_._impl_._cached_size_);
}void Info::MergeImpl(::google::protobuf::MessageLite& to_msg, const ::google::protobuf::MessageLite& from_msg) {auto* const _this = static_cast<Info*>(&to_msg);auto& from = static_cast<const Info&>(from_msg);// @@protoc_insertion_point(class_specific_merge_from_start:contact.Info)ABSL_DCHECK_NE(&from, _this);::uint32_t cached_has_bits = 0;(void) cached_has_bits;cached_has_bits = from._impl_._has_bits_[0];if ((cached_has_bits & 0x00000003u) != 0) {if ((cached_has_bits & 0x00000001u) != 0) {if (!from._internal_name().empty()) {_this->_internal_set_name(from._internal_name());} else {if (_this->_impl_.name_.IsDefault()) {_this->_internal_set_name("");}}}if ((cached_has_bits & 0x00000002u) != 0) {if (from._internal_age() != 0) {_this->_impl_.age_ = from._impl_.age_;}}}_this->_impl_._has_bits_[0] |= cached_has_bits;_this->_internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>(from._internal_metadata_);
}void Info::CopyFrom(const Info& from) {
// @@protoc_insertion_point(class_specific_copy_from_start:contact.Info)if (&from == this) return;Clear();MergeFrom(from);
}void Info::InternalSwap(Info* PROTOBUF_RESTRICT PROTOBUF_NONNULL other) {using ::std::swap;auto* arena = GetArena();ABSL_DCHECK_EQ(arena, other->GetArena());_internal_metadata_.InternalSwap(&other->_internal_metadata_);swap(_impl_._has_bits_[0], other->_impl_._has_bits_[0]);::_pbi::ArenaStringPtr::InternalSwap(&_impl_.name_, &other->_impl_.name_, arena);swap(_impl_.age_, other->_impl_.age_);
}::google::protobuf::Metadata Info::GetMetadata() const {return ::google::protobuf::Message::GetMetadataImpl(GetClassData()->full());
}
// @@protoc_insertion_point(namespace_scope)
}  // namespace contact
namespace google {
namespace protobuf {
}  // namespace protobuf
}  // namespace google
// @@protoc_insertion_point(global_scope)
PROTOBUF_ATTRIBUTE_INIT_PRIORITY2 static ::std::false_type_static_init2_ [[maybe_unused]] =(::_pbi::AddDescriptors(&descriptor_table_contact_2eproto),::std::false_type{});
#include "google/protobuf/port_undef.inc"
// Generated by the protocol buffer compiler.  DO NOT EDIT!
// NO CHECKED-IN PROTOBUF GENCODE
// source: contact.proto
// Protobuf C++ Version: 6.31.0#ifndef contact_2eproto_2epb_2eh
#define contact_2eproto_2epb_2eh#include <limits>
#include <string>
#include <type_traits>
#include <utility>#include "google/protobuf/runtime_version.h"
#if PROTOBUF_VERSION != 6031000
#error "Protobuf C++ gencode is built with an incompatible version of"
#error "Protobuf C++ headers/runtime. See"
#error "https://protobuf.dev/support/cross-version-runtime-guarantee/#cpp"
#endif
#include "google/protobuf/io/coded_stream.h"
#include "google/protobuf/arena.h"
#include "google/protobuf/arenastring.h"
#include "google/protobuf/generated_message_tctable_decl.h"
#include "google/protobuf/generated_message_util.h"
#include "google/protobuf/metadata_lite.h"
#include "google/protobuf/generated_message_reflection.h"
#include "google/protobuf/message.h"
#include "google/protobuf/message_lite.h"
#include "google/protobuf/repeated_field.h"  // IWYU pragma: export
#include "google/protobuf/extension_set.h"  // IWYU pragma: export
#include "google/protobuf/unknown_field_set.h"
// @@protoc_insertion_point(includes)// Must be included last.
#include "google/protobuf/port_def.inc"#define PROTOBUF_INTERNAL_EXPORT_contact_2eprotonamespace google {
namespace protobuf {
namespace internal {
template <typename T>
::absl::string_view GetAnyMessageName();
}  // namespace internal
}  // namespace protobuf
}  // namespace google// Internal implementation detail -- do not use these members.
struct TableStruct_contact_2eproto {static const ::uint32_t offsets[];
};
extern "C" {
extern const ::google::protobuf::internal::DescriptorTable descriptor_table_contact_2eproto;
}  // extern "C"
namespace contact {
class Info;
struct InfoDefaultTypeInternal;
extern InfoDefaultTypeInternal _Info_default_instance_;
extern const ::google::protobuf::internal::ClassDataFull Info_class_data_;
}  // namespace contact
namespace google {
namespace protobuf {
}  // namespace protobuf
}  // namespace googlenamespace contact {// ===================================================================// -------------------------------------------------------------------class Info final : public ::google::protobuf::Message
/* @@protoc_insertion_point(class_definition:contact.Info) */ {public:inline Info() : Info(nullptr) {}~Info() PROTOBUF_FINAL;#if defined(PROTOBUF_CUSTOM_VTABLE)void operator delete(Info* PROTOBUF_NONNULL msg, std::destroying_delete_t) {SharedDtor(*msg);::google::protobuf::internal::SizedDelete(msg, sizeof(Info));}
#endiftemplate <typename = void>explicit PROTOBUF_CONSTEXPR Info(::google::protobuf::internal::ConstantInitialized);inline Info(const Info& from) : Info(nullptr, from) {}inline Info(Info&& from) noexcept: Info(nullptr, ::std::move(from)) {}inline Info& operator=(const Info& from) {CopyFrom(from);return *this;}inline Info& operator=(Info&& from) noexcept {if (this == &from) return *this;if (::google::protobuf::internal::CanMoveWithInternalSwap(GetArena(), from.GetArena())) {InternalSwap(&from);} else {CopyFrom(from);}return *this;}inline const ::google::protobuf::UnknownFieldSet& unknown_fields() constABSL_ATTRIBUTE_LIFETIME_BOUND {return _internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance);}inline ::google::protobuf::UnknownFieldSet* PROTOBUF_NONNULL mutable_unknown_fields()ABSL_ATTRIBUTE_LIFETIME_BOUND {return _internal_metadata_.mutable_unknown_fields<::google::protobuf::UnknownFieldSet>();}static const ::google::protobuf::Descriptor* PROTOBUF_NONNULL descriptor() {return GetDescriptor();}static const ::google::protobuf::Descriptor* PROTOBUF_NONNULL GetDescriptor() {return default_instance().GetMetadata().descriptor;}static const ::google::protobuf::Reflection* PROTOBUF_NONNULL GetReflection() {return default_instance().GetMetadata().reflection;}static const Info& default_instance() {return *reinterpret_cast<const Info*>(&_Info_default_instance_);}static constexpr int kIndexInFileMessages = 0;friend void swap(Info& a, Info& b) { a.Swap(&b); }inline void Swap(Info* PROTOBUF_NONNULL other) {if (other == this) return;if (::google::protobuf::internal::CanUseInternalSwap(GetArena(), other->GetArena())) {InternalSwap(other);} else {::google::protobuf::internal::GenericSwap(this, other);}}void UnsafeArenaSwap(Info* PROTOBUF_NONNULL other) {if (other == this) return;ABSL_DCHECK(GetArena() == other->GetArena());InternalSwap(other);}// implements Message ----------------------------------------------Info* PROTOBUF_NONNULL New(::google::protobuf::Arena* PROTOBUF_NULLABLE arena = nullptr) const {return ::google::protobuf::Message::DefaultConstruct<Info>(arena);}using ::google::protobuf::Message::CopyFrom;void CopyFrom(const Info& from);using ::google::protobuf::Message::MergeFrom;void MergeFrom(const Info& from) { Info::MergeImpl(*this, from); }private:static void MergeImpl(::google::protobuf::MessageLite& to_msg,const ::google::protobuf::MessageLite& from_msg);public:bool IsInitialized() const {return true;}ABSL_ATTRIBUTE_REINITIALIZES void Clear() PROTOBUF_FINAL;#if defined(PROTOBUF_CUSTOM_VTABLE)private:static ::size_t ByteSizeLong(const ::google::protobuf::MessageLite& msg);static ::uint8_t* PROTOBUF_NONNULL _InternalSerialize(const ::google::protobuf::MessageLite& msg, ::uint8_t* PROTOBUF_NONNULL target,::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream);public:::size_t ByteSizeLong() const { return ByteSizeLong(*this); }::uint8_t* PROTOBUF_NONNULL _InternalSerialize(::uint8_t* PROTOBUF_NONNULL target,::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) const {return _InternalSerialize(*this, target, stream);}#else   // PROTOBUF_CUSTOM_VTABLE::size_t ByteSizeLong() const final;::uint8_t* PROTOBUF_NONNULL _InternalSerialize(::uint8_t* PROTOBUF_NONNULL target,::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) const final;#endif  // PROTOBUF_CUSTOM_VTABLEint GetCachedSize() const { return _impl_._cached_size_.Get(); }private:void SharedCtor(::google::protobuf::Arena* PROTOBUF_NULLABLE arena);static void SharedDtor(MessageLite& self);void InternalSwap(Info* PROTOBUF_NONNULL other);private:template <typename T>friend ::absl::string_view(::google::protobuf::internal::GetAnyMessageName)();static ::absl::string_view FullMessageName() { return "contact.Info"; }protected:explicit Info(::google::protobuf::Arena* PROTOBUF_NULLABLE arena);Info(::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const Info& from);Info(::google::protobuf::Arena* PROTOBUF_NULLABLE arena, Info&& from) noexcept: Info(arena) {*this = ::std::move(from);}const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL GetClassData() const PROTOBUF_FINAL;static void* PROTOBUF_NONNULL PlacementNew_(const void* PROTOBUF_NONNULL, void* PROTOBUF_NONNULL mem,::google::protobuf::Arena* PROTOBUF_NULLABLE arena);static constexpr auto InternalNewImpl_();public:static constexpr auto InternalGenerateClassData_();::google::protobuf::Metadata GetMetadata() const;// nested types ----------------------------------------------------// accessors -------------------------------------------------------enum : int {kNameFieldNumber = 1,kAgeFieldNumber = 2,};// string name = 1;void clear_name() ;const ::std::string& name() const;template <typename Arg_ = const ::std::string&, typename... Args_>void set_name(Arg_&& arg, Args_... args);::std::string* PROTOBUF_NONNULL mutable_name();[[nodiscard]] ::std::string* PROTOBUF_NULLABLE release_name();void set_allocated_name(::std::string* PROTOBUF_NULLABLE value);private:const ::std::string& _internal_name() const;PROTOBUF_ALWAYS_INLINE void _internal_set_name(const ::std::string& value);::std::string* PROTOBUF_NONNULL _internal_mutable_name();public:// int32 age = 2;void clear_age() ;::int32_t age() const;void set_age(::int32_t value);private:::int32_t _internal_age() const;void _internal_set_age(::int32_t value);public:// @@protoc_insertion_point(class_scope:contact.Info)private:class _Internal;friend class ::google::protobuf::internal::TcParser;static const ::google::protobuf::internal::TcParseTable<1, 2,0, 25,2>_table_;friend class ::google::protobuf::MessageLite;friend class ::google::protobuf::Arena;template <typename T>friend class ::google::protobuf::Arena::InternalHelper;using InternalArenaConstructable_ = void;using DestructorSkippable_ = void;struct Impl_ {inline explicit constexpr Impl_(::google::protobuf::internal::ConstantInitialized) noexcept;inline explicit Impl_(::google::protobuf::internal::InternalVisibility visibility,::google::protobuf::Arena* PROTOBUF_NULLABLE arena);inline explicit Impl_(::google::protobuf::internal::InternalVisibility visibility,::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const Impl_& from,const Info& from_msg);::google::protobuf::internal::HasBits<1> _has_bits_;::google::protobuf::internal::CachedSize _cached_size_;::google::protobuf::internal::ArenaStringPtr name_;::int32_t age_;PROTOBUF_TSAN_DECLARE_MEMBER};union { Impl_ _impl_; };friend struct ::TableStruct_contact_2eproto;
};extern const ::google::protobuf::internal::ClassDataFull Info_class_data_;// ===================================================================// ===================================================================#ifdef __GNUC__
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wstrict-aliasing"
#endif  // __GNUC__
// -------------------------------------------------------------------// Info// string name = 1;
inline void Info::clear_name() {::google::protobuf::internal::TSanWrite(&_impl_);_impl_.name_.ClearToEmpty();_impl_._has_bits_[0] &= ~0x00000001u;
}
inline const ::std::string& Info::name() constABSL_ATTRIBUTE_LIFETIME_BOUND {// @@protoc_insertion_point(field_get:contact.Info.name)return _internal_name();
}
template <typename Arg_, typename... Args_>
PROTOBUF_ALWAYS_INLINE void Info::set_name(Arg_&& arg, Args_... args) {::google::protobuf::internal::TSanWrite(&_impl_);_impl_._has_bits_[0] |= 0x00000001u;_impl_.name_.Set(static_cast<Arg_&&>(arg), args..., GetArena());// @@protoc_insertion_point(field_set:contact.Info.name)
}
inline ::std::string* PROTOBUF_NONNULL Info::mutable_name()ABSL_ATTRIBUTE_LIFETIME_BOUND {::std::string* _s = _internal_mutable_name();// @@protoc_insertion_point(field_mutable:contact.Info.name)return _s;
}
inline const ::std::string& Info::_internal_name() const {::google::protobuf::internal::TSanRead(&_impl_);return _impl_.name_.Get();
}
inline void Info::_internal_set_name(const ::std::string& value) {::google::protobuf::internal::TSanWrite(&_impl_);_impl_._has_bits_[0] |= 0x00000001u;_impl_.name_.Set(value, GetArena());
}
inline ::std::string* PROTOBUF_NONNULL Info::_internal_mutable_name() {::google::protobuf::internal::TSanWrite(&_impl_);_impl_._has_bits_[0] |= 0x00000001u;return _impl_.name_.Mutable( GetArena());
}
inline ::std::string* PROTOBUF_NULLABLE Info::release_name() {::google::protobuf::internal::TSanWrite(&_impl_);// @@protoc_insertion_point(field_release:contact.Info.name)if ((_impl_._has_bits_[0] & 0x00000001u) == 0) {return nullptr;}_impl_._has_bits_[0] &= ~0x00000001u;auto* released = _impl_.name_.Release();if (::google::protobuf::internal::DebugHardenForceCopyDefaultString()) {_impl_.name_.Set("", GetArena());}return released;
}
inline void Info::set_allocated_name(::std::string* PROTOBUF_NULLABLE value) {::google::protobuf::internal::TSanWrite(&_impl_);if (value != nullptr) {_impl_._has_bits_[0] |= 0x00000001u;} else {_impl_._has_bits_[0] &= ~0x00000001u;}_impl_.name_.SetAllocated(value, GetArena());if (::google::protobuf::internal::DebugHardenForceCopyDefaultString() && _impl_.name_.IsDefault()) {_impl_.name_.Set("", GetArena());}// @@protoc_insertion_point(field_set_allocated:contact.Info.name)
}// int32 age = 2;
inline void Info::clear_age() {::google::protobuf::internal::TSanWrite(&_impl_);_impl_.age_ = 0;_impl_._has_bits_[0] &= ~0x00000002u;
}
inline ::int32_t Info::age() const {// @@protoc_insertion_point(field_get:contact.Info.age)return _internal_age();
}
inline void Info::set_age(::int32_t value) {_internal_set_age(value);_impl_._has_bits_[0] |= 0x00000002u;// @@protoc_insertion_point(field_set:contact.Info.age)
}
inline ::int32_t Info::_internal_age() const {::google::protobuf::internal::TSanRead(&_impl_);return _impl_.age_;
}
inline void Info::_internal_set_age(::int32_t value) {::google::protobuf::internal::TSanWrite(&_impl_);_impl_.age_ = value;
}#ifdef __GNUC__
#pragma GCC diagnostic pop
#endif  // __GNUC__// @@protoc_insertion_point(namespace_scope)
}  // namespace contact// @@protoc_insertion_point(global_scope)#include "google/protobuf/port_undef.inc"#endif  // contact_2eproto_2epb_2eh

假如在main函数中需要对PersonInfo类进行使用,需要包含生成的头文件,此外在编译的时候,还需要指定使用-std=c++11选项以及编译连接库 -lprotobuf。

示例:

#include<iostream>
#include"contact.pb.h"
#include<string>
using std::endl;
using std::cout;
using std::cerr;
int main()
{std::string people_str;{contact::PersonInfo info1;info1.set_age(21);info1.set_name("张三");if(!info1.SerializeToString(&people_str)){cerr<<"序列化失败"<<endl;exit(-1);}        cout<<"序列化成功"<<endl;cout<<"people_str:"<<people_str<<endl;cout<<"---------------------------------"<<endl;}{contact::PersonInfo info1;if(!info1.ParseFromString(people_str)){cerr<<"反序列化失败"<<endl;exit(-1);}        cout<<"反序列化成功"<<endl;cout<<"name:"<<info1.name()<<endl;cout<<"age:"<<info1.age()<<endl;}return 0;
}

运行结果:
在这里插入图片描述

4、在网络通信或存储中使用protobuf序列化数据

和本地是相同的,这里不再演示,在后面的讲解和实际项目中再详细展示。


四、快速上手写一个小需求来熟悉如何编写proto文件?

需求: 我们正在开发一个简单的图书管理系统。需要在客户端和服务器之间传输图书信息。每本图书包含以下内容:

  • 图书ID(整数)
  • 书名(字符串)
  • 作者(字符串)
  • 出版年份(整数,可选)
  • 是否借出(布尔值)
  • 借阅人(字符串,可选,仅在借出时填写)

请根据这个需求,设计一个合适的proto文件。


比较完善的答案如下:

//声明语法版本
syntax = "proto3";package books;// 单本图书信息
message Book {int64 id = 1;                  // 图书IDstring title = 2;              // 书名string author = 3;             // 作者int32 year = 4;                // 出版年份(可选,未知为0)bool is_borrowed = 5;          // 是否借出string borrower = 6;           // 借阅人(仅借出时填写,否则为空字符串)
}

完~
在这里插入图片描述

未经作者同意禁止转载

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.pswp.cn/bicheng/82925.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

uniapp调用java接口 跨域问题

前言 之前在Windows10本地 调试一个旧项目&#xff0c;手机移动端用的是Uni-app&#xff0c;vue的版本是v2。后端是java spring-boot。运行手机移动端的首页请求后台接口老是提示错误信息。 错误信息如下&#xff1a; Access to XMLHttpRequest at http://localhost:8080/api/…

[ Qt ] | Qlabel使用

目录 属性 setTextFormat 插入图片 设置图片根据窗口大小实时变化 边框和对其方式 ​编辑 设置缩进 设置伙伴 Qlabel可以用来显式图片和文字 属性 text textFormat Qlabel独有的机制&#xff1a;buddy setTextFormat 插入图片 设置图片根据窗口大小实时变化 Qt中表…

Springboot 项目一启动就获取HttpSession

在 Spring Boot 项目中&#xff0c;HttpSession 是有状态的&#xff0c;通常只有在用户发起 HTTP 请求并建立会话后才会创建。因此&#xff0c;在项目启动时&#xff08;即应用刚启动还未处理任何请求&#xff09;是无法获取到 HttpSession 的。 方法一&#xff1a;使用 HttpS…

Step9—Ambari Web UI 初始化安装 (Ambari3.0.0)

Ambari Web UI 安装 如果还不会系统性的部署&#xff0c;或者前置内容不熟悉&#xff0c;建议从Step1 开始阅读。不通版本针对于不同操作系统可能存在差异&#xff01;这里我也整理好了 https://doc.janettr.com/install/manual/ 1. 进入 Ambari Web UI 并登录 在浏览器中访…

热门大型语言模型(LLM)应用开发框架

我们来深入探索这些强大的大型语言模型&#xff08;LLM&#xff09;应用开发框架&#xff0c;并且我会尝试用文本形式描述一些核心的流程图&#xff0c;帮助您更好地理解它们的工作机制。由于我无法直接生成图片&#xff0c;我会用文字清晰地描述流程图的各个步骤和连接。 Lang…

机器学习数据降维方法

1.数据类型 2.如何选择降维方法进行数据降维 3.线性降维&#xff1a;主成分分析&#xff08;PCA&#xff09;、线性判别分析&#xff08;LDA&#xff09; 4.非线性降维 5.基于特征选择的降维 6.基于神经网络的降维 数据降维是将高维数据转换为低维表示的过程&#xff0c;旨在保…

太阳系运行模拟程序-html动画

太阳系运行模拟程序-html动画 by AI: <!DOCTYPE html> <html lang"zh"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>交互式太阳系…

2025年全国青少年信息素养大赛 scratch图形化编程挑战赛 小低组初赛 内部集训模拟题解析

2025年信息素养大赛初赛scratch模拟题解析 博主推荐 所有考级比赛学习相关资料合集【推荐收藏】 scratch资料 Scratch3.0系列视频课程资料零基础学习scratch3.0【入门教学 免费】零基础学习scratch3.0【视频教程 114节 免费】 历届蓝桥杯scratch国赛真题解析历届蓝桥杯scr…

grid网格布局

使用flex布局的痛点 如果使用justify-content: space-between;让子元素两端对齐&#xff0c;自动分配中间间距&#xff0c;假设一行4个&#xff0c;如果每一行都是4的倍数那没任何问题&#xff0c;但如果最后一行是2、3个的时候就会出现下面的状况&#xff1a; /* flex布局 两…

通义灵码2.5——基于MCP实现我的12306火车票智能查询小助手

本文因排版显示问题&#xff0c;为保证阅读体验&#xff0c;请大家访问&#xff1a; 通义灵码2.5——基于MCP打造我的12306火车票智能查询小助手-CSDN博客 前沿技术应用全景图 本项目作为通义灵码2.5的标杆实践案例&#xff0c;展现了AI辅助开发在复杂业务系统中的革命性突破…

Unity Button 交互动画

在UGUI的Button组件中&#xff0c;有一个过渡动画表现的功能。可以对按钮的不同交互状态添加交互反馈动画&#xff0c;来提高玩家的交互体验。 交互状态 名称 描述 Normal 正常情况 Highlighted 高亮显示&#xff0c;例如鼠标触碰到按钮点击范围 Pressed 按钮被按下的时…

钉钉热点实时推送助理-思路篇

以下是针对热点实时推送助理的功能描述&#xff0c;结合机器学习技术栈与用户场景的通俗化解释&#xff1a; 快速体验的话直接用钉钉扫描下方二维码体验 1. 核心功能 &#xff08;1&#xff09;热点抓取引擎 类比&#xff1a;像蜘蛛爬取全网信息&#xff08;网络爬虫信息抽取…

remote: error: hook declined to update refs/heads.....

gitee拉取分支&#xff0c;修改上传出现的问题&#xff0c;折腾了好久&#xff0c;浅浅记录. 1. 首次克隆仓库 # 克隆仓库&#xff08;使用 HTTPS 或 SSH&#xff09; git clone ------------ cd xxx-project2. 配置正确的用户信息&#xff08;关键步骤&#xff01;&#xff…

使用Vue + Element Plus实现可多行编辑的分页表格

需求背景&#xff1a; 在现代前端开发中&#xff0c;表格作为数据展示和交互的重要组件&#xff0c;在各类管理系统、数据平台中有着广泛的应用。随着用户对数据操作便捷性要求的不断提高&#xff0c;具备灵活编辑功能的表格成为了开发中的常见需求。特别是在需求处理大…

奥威BI+AI——高效智能数据分析工具,引领数据分析新时代

随着数据量的激增&#xff0c;企业对高效、智能的数据分析工具——奥威BIAI的需求日益迫切。奥威BIAI&#xff0c;作为一款颠覆性的数据分析工具&#xff0c;凭借其独特功能&#xff0c;正在引领数据分析领域的新纪元。 一、‌零报表环境下的极致体验‌ 奥威BIAI突破传统报表限…

【机器学习基础】机器学习入门核心算法:K均值(K-Means)

机器学习入门核心算法&#xff1a;K均值&#xff08;K-Means&#xff09; 1. 算法逻辑2. 算法原理与数学推导2.1 目标函数2.2 数学推导2.3 时间复杂度 3. 模型评估内部评估指标外部评估指标&#xff08;需真实标签&#xff09; 4. 应用案例4.1 客户细分4.2 图像压缩4.3 文档聚类…

springboot多模块父pom打包正常,单模块报错

背景&#xff1a;因为项目开发中经常发测试环境&#xff0c;发现使用阿里的插件能一键上传&#xff0c;不用手动上传比较方便。但是多模块有多个启动jar的时候&#xff0c;全局打包太慢&#xff0c;单独打发现报错。这里贴一下我使用这个插件的方式&#xff1a; 附带一个我感觉…

通义灵码2.5——基于MCP打造我的12306火车票智能查询小助手

前沿技术应用全景图 本项目作为通义灵码2.5的标杆实践案例&#xff0c;展现了AI辅助开发在复杂业务系统中的革命性突破。通过深度集成12306 MCP服务体系&#xff0c;我们构建了一个融合智能决策、环境感知和自主优化的新一代火车票查询系统。 #mermaid-svg-4D7QqwJjsQRdKVP7 {…

进程间通信(共享内存)

目录 前置&#xff1a; 一 原理 二 API 1. shmgetr 2. shmctl 3. 指令操作 2. 删除 3. 挂接 4. 断开挂接 三 demo代码 四 共享内存的特征 前置&#xff1a; 1.前面说的不管是匿名管道还是命名管道都是基于文件的思想构建的一套进程间通信的方案&#xff0c;那有没有…

详解GPU

详解GPU GPU&#xff08;图形处理器&#xff09;就像电脑里的 “图形小能手”&#xff0c;原本主要用来画画&#xff08;渲染图形&#xff09;&#xff0c;现在还能帮忙干很多杂活&#xff08;并行计算&#xff09; 一、先认识 GPU 的 “钥匙”&#xff1a;驱动和开发工具 装驱…