跳到主要内容

protobuf

https://protobuf.dev/overview/ https://github.com/protocolbuffers/protobuf/releases

Updating Proto Definitions Without Updating Code

It’s standard for software products to be backward compatible, but it is less common for them to be forward compatible. As long as you follow some simple practices when updating .proto definitions, old code will read new messages without issues, ignoring any newly added fields. To the old code, fields that were deleted will have their default value, and deleted repeated fields will be empty. For information on what “repeated” fields are, see Protocol Buffers Definition Syntax later in this topic.

New code will also transparently read old messages. New fields will not be present in old messages; in these cases protocol buffers provide a reasonable default value

https://protobuf.dev/programming-guides/proto3/

Deleting Fields

When you no longer need a field and all references have been deleted from client code, you may delete the field definition from the message. However, you must reserve the deleted field number

You should also reserve the field name to allow JSON and TextFormat encodings of your message to continue to parse.

Reserved Fields

message Foo {
reserved 2, 15, 9 to 11;
reserved "foo", "bar";
}

Default Values

When a message is parsed, if the encoded message does not contain a particular implicit presence element, accessing the corresponding field in the parsed object returns the default value for that field

Enumerations

every enum definition must contain a constant that maps to zero as its first element

You can define aliases by assigning the same value to different enum constants. To do this you need to set the allow_alias option to true. Otherwise, the protocol buffer compiler generates a warning message when aliases are found. Though all alias values are valid during deserialization, the first value is always used when serializing

Importing Definitions

You can use definitions from other .proto files by importing them. To import another .proto’s definitions, you add an import statement to the top of your file

import "myproject/other_protos.proto";

The protocol compiler searches for imported files in a set of directories specified on the protocol compiler command line using the -I/--proto_path flag

Any

An Any contains an arbitrary serialized message as bytes, along with a URL that acts as a globally unique identifier for and resolves to that message’s type. To use the Any type, you need to import google/protobuf/any.proto

The default type URL for a given message type is type.googleapis.com/_packagename_._messagename_

Oneof

You can check which value in a oneof is set (if any) using a special case() or WhichOneof() method, depending on your chosen language

message SampleMessage {
oneof test_oneof {
string name = 4;
SubMessage sub_message = 9;
}
}

Maps

map<key_type, value_type> map_field = N;

Packages

The way a package specifier affects the generated code depends on your chosen language

  • In Python, the package directive is ignored, since Python modules are organized according to their location in the file system
  • In Go, the package directive is ignored, and the generated .pb.go file is in the package named after the corresponding go_proto_library Bazel rule. For open source projects, you must provide either a go_package option or set the Bazel -M flag.

Options

Some options are file-level options, meaning they should be written at the top-level scope, not inside any message, enum, or service definition. Some options are message-level options, meaning they should be written inside message definitions. Some options are field-level options, meaning they should be written inside field definitions

Generating Your Classes

For Go, you also need to install a special code generator plugin for the compiler

protoc --proto_path=IMPORT_PATH --cpp_out=DST_DIR --java_out=DST_DIR --python_out=DST_DIR --go_out=DST_DIR --ruby_out=DST_DIR --objc_out=DST_DIR --csharp_out=DST_DIR path/to/file.proto

-I=_IMPORT_PATH_ can be used as a short form of --proto_path

You must provide one or more .proto files as input. Multiple .proto files can be specified at once. Although the files are named relative to the current directory, each file must reside in one of the IMPORT_PATHs so that the compiler can determine its canonical name