Documentation
¶
Overview ¶
Package proto defines the foundational interface hierarchy for protobuf messages, following the Interface Segregation Principle (ISP). It provides nine focused, single-method interfaces that each describe one capability of a protobuf message:
- MarshalAppender: append-style serialization
- Marshaler: convenience allocation-based serialization
- Unmarshaler: wire-format deserialization
- Sizer: deterministic serialized-size pre-computation
- Merger: protobuf merge semantics
- Cloner: deep copy with no shared backing memory
- Resetter: zero-state reset for object reuse
- Validator: schema constraint validation
- ProtoReflector: access to runtime reflection metadata
The composite Message interface embeds all nine individual interfaces and represents the full contract that generated message types are expected to satisfy. Consumers should accept the narrowest interface required by their function rather than demanding the full Message contract, following the ISP design principle.
MarshalAppender and Sizer have method signatures structurally identical to their counterparts in the pool package (pool.MarshalAppender and pool.Sizer). Because Go uses structural (duck) typing for interface satisfaction, any concrete type that satisfies one automatically satisfies the other without any import relationship between the two packages.
MessageReflection is a type alias for protoreflect.Message, bridging the proto package's ProtoReflector interface with the full reflection contract defined in the protoreflect package.
Package proto -- equal_field.go contains field-level equality comparison functions for singular, list, and map fields, dispatching on the field kind to handle messages, bytes, floats, enums, and other scalars.
Package proto -- equal_list_map.go contains diff collection functions for list and map fields, producing human-readable difference descriptions with indexed or keyed paths.
Package proto -- equal_message.go contains the top-level Equal and Diff functions, the core reflected message equality comparison, and the diff collection logic with path tracking.
Package proto -- unsafe_options.go defines the UnsafeUnmarshalOptions type for controlling zero-copy string and bytes unmarshal behavior.
Index ¶
- func Bool(v bool) *bool
- func ClearExtension(msg Message, xt *ExtensionType)
- func Diff(a, b Message) string
- func Equal(a, b Message) bool
- func Float32(v float32) *float32
- func Float64(v float64) *float64
- func GetExtension(msg Message, xt *ExtensionType) protoreflect.Value
- func GetOption(optionsMsg Message, xt *ExtensionType) (v protoreflect.Value, err error)
- func HasExtension(msg Message, xt *ExtensionType) bool
- func Int32(v int32) *int32
- func Int64(v int64) *int64
- func Merge(dst, src Message)
- func RegisterNewMessageFactory(fn func(descriptor.MessageDescriptorAccessor) protoreflect.Message)
- func SetExtension(msg Message, xt *ExtensionType, v protoreflect.Value)
- func String(v string) *string
- func Uint32(v uint32) *uint32
- func Uint64(v uint64) *uint64
- type Cloner
- type ExtensionType
- type GetOptionError
- type MarshalAppender
- type Marshaler
- type Merger
- type Message
- type MessageReflection
- type ProtoReflector
- type Resetter
- type Sizer
- type Unmarshaler
- type UnsafeUnmarshalOptions
- type Validator
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func ClearExtension ¶
func ClearExtension(msg Message, xt *ExtensionType)
ClearExtension clears the extension field on msg, returning it to its default state. It panics if the message's full name does not match the extension's extendee or if the extension's field number is outside the extendee's declared extension ranges.
func Diff ¶
Diff returns a human-readable string describing all structural differences between two protobuf messages. An empty string means the messages are equal.
func Equal ¶
Equal reports whether two messages are structurally equal per protobuf semantics. Both nil arguments means equal. One nil and one non-nil means not equal. Messages with different descriptor full names are not equal (no panic).
Scalar fields are compared by value, enum fields by their integer EnumNumber, bytes fields by content (nil and empty are equivalent), and float fields treat NaN == NaN (protobuf convention). Unknown fields are compared via byte-level equality.
Repeated fields are compared element-by-element in order. Map fields are compared independent of insertion order. Nested message fields are compared recursively. Oneof fields are compared by the active variant and its value.
An unset repeated field and an empty repeated field are considered equal (both have length 0). An unset map field and an empty map field are considered equal (both have length 0).
func GetExtension ¶
func GetExtension(msg Message, xt *ExtensionType) protoreflect.Value
GetExtension returns the value of the extension field on msg. It panics if the message's full name does not match the extension's extendee or if the extension's field number is outside the extendee's declared extension ranges.
func GetOption ¶
func GetOption(optionsMsg Message, xt *ExtensionType) (v protoreflect.Value, err error)
GetOption reads a custom option value from an already-unmarshaled options message. It wraps GetExtension in a deferred panic recovery so that validation failures (wrong message type, out-of-range field number) are returned as errors instead of panics.
If optionsMsg is nil, GetOption returns the zero/default value for the extension's kind and a nil error. This handles the common case where no options were set on a descriptor.
The caller is responsible for constructing and unmarshaling optionsMsg with the appropriate extension resolver before passing it to GetOption. This design avoids import cycles between the proto and dynamicpb packages.
func HasExtension ¶
func HasExtension(msg Message, xt *ExtensionType) bool
HasExtension reports whether the extension field is populated on msg. It panics if the message's full name does not match the extension's extendee or if the extension's field number is outside the extendee's declared extension ranges.
func Merge ¶
func Merge(dst, src Message)
Merge merges all populated fields from src into dst. Scalar fields from src overwrite dst only when populated; bytes fields are defensively copied; repeated fields are appended; map fields merge by key; message fields are recursively merged; unknown fields from src are appended to dst. Merge panics if dst is nil, or if src and dst have different message descriptor full names.
Merge delegates to the fast-path dst.Merge(src) method via the Merger interface, which is embedded in proto.Message and therefore always available. The FullName check here is redundant with the one inside dst.Merge, but provides a consistent panic message at the proto package level.
If src is nil, Merge is a no-op and returns immediately.
func RegisterNewMessageFactory ¶
func RegisterNewMessageFactory(fn func(descriptor.MessageDescriptorAccessor) protoreflect.Message)
RegisterNewMessageFactory sets the factory function used by ExtensionType.New to create message-typed extension zero values. This is called by the dynamicpb package at init time.
func SetExtension ¶
func SetExtension(msg Message, xt *ExtensionType, v protoreflect.Value)
SetExtension sets the value of the extension field on msg. It panics if the message's full name does not match the extension's extendee or if the extension's field number is outside the extendee's declared extension ranges.
Types ¶
type Cloner ¶
type Cloner interface {
Clone() Message
}
Cloner is the interface for deep copy. An implementation returns a new Message value that is a complete, independent copy of the receiver. The returned value shares no backing memory with the original; mutations to either do not affect the other. The return type is the composite Message interface so callers can continue to use the full contract on the clone.
type ExtensionType ¶
type ExtensionType struct {
// contains filtered or unexported fields
}
ExtensionType represents a registered extension field type. It is a value type that wraps a field descriptor and the extendee message descriptor, providing type-safe access to extension metadata and zero-value construction.
func NewExtensionType ¶
func NewExtensionType(desc descriptor.FieldDescriptorAccessor, extendee descriptor.MessageDescriptorAccessor) ExtensionType
NewExtensionType creates an ExtensionType from an extension field descriptor and the message descriptor being extended.
func (ExtensionType) ExtendedType ¶
func (xt ExtensionType) ExtendedType() descriptor.MessageDescriptorAccessor
ExtendedType returns the message descriptor of the message being extended.
func (ExtensionType) IsValidExtension ¶
func (xt ExtensionType) IsValidExtension(msg Message) bool
IsValidExtension reports whether the extension is valid for the given message. It checks that the message's descriptor full name matches the extendee and that the extension's field number falls within the extendee's declared extension ranges.
func (ExtensionType) New ¶
func (xt ExtensionType) New() protoreflect.Value
New returns the zero/default value for the extension field's kind. For scalar kinds it returns the appropriate zero value (0, false, "", nil). For message kinds it returns a new empty dynamic message created via the registered message factory. If no factory is available, it returns an invalid Value.
func (ExtensionType) TypeDescriptor ¶
func (xt ExtensionType) TypeDescriptor() descriptor.FieldDescriptorAccessor
TypeDescriptor returns the extension's field descriptor.
type GetOptionError ¶
type GetOptionError struct {
PanicValue interface{}
}
GetOptionError represents a recovered panic from GetOption. It wraps the original panic value as context.
func (*GetOptionError) Error ¶
func (e *GetOptionError) Error() string
Error returns a human-readable message for the recovered panic.
type MarshalAppender ¶
MarshalAppender is the interface for append-style serialization. An implementation appends the serialized form of the receiver to b and returns the extended slice. The error return covers message-level failures such as required fields missing or values out of range.
MarshalAppender has a method signature structurally identical to pool.MarshalAppender. Because Go uses structural typing for interface satisfaction, any concrete type that satisfies proto.MarshalAppender also satisfies pool.MarshalAppender, and vice versa, without any import relationship between the two packages.
type Marshaler ¶
Marshaler is the interface for convenience allocation-based serialization. An implementation allocates and returns a new byte slice containing the serialized form of the receiver.
Marshaler is distinct from pool.Marshaler, which is a composite interface embedding MarshalAppender and Sizer. This interface defines a single method with a different signature and semantics.
type Merger ¶
Merger is the interface for protobuf merge semantics. An implementation merges the fields of src into the receiver: singular fields are overwritten, repeated fields are concatenated, and nested messages are recursively merged. The src parameter is typed as the composite Message interface; implementations may type-assert to their concrete type for performance. The error return covers type mismatch when merging incompatible message types.
type Message ¶
type Message interface {
MarshalAppender
Marshaler
Unmarshaler
Sizer
Merger
Cloner
Resetter
Validator
ProtoReflector
}
Message is the composite interface that represents the full contract for generated protobuf message types. It embeds all nine individual interfaces: MarshalAppender, Marshaler, Unmarshaler, Sizer, Merger, Cloner, Resetter, Validator, and ProtoReflector. Generated types verify satisfaction via compile-time checks of the form: var _ Message = (*GeneratedType)(nil).
Consumers should accept the narrowest interface needed by their function rather than requiring the full Message contract. For example, a function that only computes serialized size should accept Sizer, not Message. This follows the Interface Segregation Principle (ISP).
func Clone ¶
Clone returns a deep copy of src as a proto.Message. The returned message shares no backing memory with the original: scalars are copied by value, bytes are defensively copied, nested messages are recursively cloned, and lists and maps are deep-copied element by element. Unknown fields are copied via a defensive byte slice copy.
If src is nil, Clone returns nil.
Clone delegates to the fast-path src.Clone() method via the Cloner interface, which is embedded in proto.Message and therefore always available.
The returned Message wraps the same concrete type as the source; callers can type-assert back to the original concrete type.
type MessageReflection ¶
type MessageReflection = protoreflect.Message
MessageReflection is a type alias for protoreflect.Message, the runtime reflection interface for protobuf messages. It provides dynamic access to message fields by descriptor, including reading and writing fields, iterating over populated fields, and accessing oneof and map fields. See the protoreflect package for the full interface contract.
This is a type alias (=), not a new type definition, so existing code referencing proto.MessageReflection remains fully compatible.
type ProtoReflector ¶
type ProtoReflector interface {
ProtoReflect() MessageReflection
}
ProtoReflector is the interface for access to runtime message reflection and descriptor metadata. An implementation returns a MessageReflection value (which resolves to protoreflect.Message via the type alias) that provides dynamic access to field descriptors, message structure, field reading and writing by descriptor, iteration over populated fields, oneof inspection, and unknown field access. See the protoreflect.Message interface for the full method contract and panic conventions.
type Resetter ¶
type Resetter interface {
Reset()
}
Resetter is the interface for zero-state reset. An implementation returns the receiver to its zero state, clearing all fields for reuse. Resetter is intended for object pool and reuse patterns where callers reset a message before populating it with new data. Calling Reset on an already-zero message must be a no-op and must not panic.
type Sizer ¶
type Sizer interface {
Size() int
}
Sizer is the interface for deterministic serialized-size pre-computation. An implementation returns the exact number of bytes the serialized form will occupy, computed without allocations and without performing any encoding. Calling Size multiple times on an unmodified value must return the same result.
Sizer has a method signature structurally identical to pool.Sizer. Because Go uses structural typing for interface satisfaction, any concrete type that satisfies proto.Sizer also satisfies pool.Sizer, and vice versa, without any import relationship between the two packages.
type Unmarshaler ¶
Unmarshaler is the interface for wire-format deserialization. An implementation populates the receiver by decoding the wire-format bytes in b. The receiver must be a pointer type; decoding into a nil receiver is invalid. The error return covers malformed wire data, unknown fields policy violations, and truncation.
type UnsafeUnmarshalOptions ¶
type UnsafeUnmarshalOptions struct {
// ZeroCopyStrings enables zero-copy string and bytes field aliasing.
// When true, generated UnmarshalUnsafe methods use unsafe.String to
// create string values that alias the input buffer, and use three-index
// slices for bytes fields that share the input buffer without copying.
// When false, UnmarshalUnsafe behaves identically to the standard
// Unmarshal method with full copies.
ZeroCopyStrings bool
}
UnsafeUnmarshalOptions controls the behavior of the generated UnmarshalUnsafe method. When ZeroCopyStrings is true, string and bytes fields in the decoded message alias the input byte slice directly instead of copying, eliminating allocation overhead for high-throughput use cases.
Safety contract: when ZeroCopyStrings is true the caller MUST guarantee that the input []byte outlives the message and is not modified while the message is in use. Violation of this contract causes undefined behavior because the message's string and bytes fields will reference the same backing memory as the input buffer.
type Validator ¶
type Validator interface {
Validate() error
}
Validator is the interface for schema constraint validation. An implementation checks that the message satisfies its schema constraints, including required fields present, values within defined ranges, and string fields valid UTF-8 where required. Validate returns nil if the message is valid, or a descriptive error identifying the first violated constraint.