This repo provides reflection APIs for protocol buffers (also known as "protobufs" for short)
and gRPC. The core of reflection in protobufs is the
descriptor.
A descriptor is itself a protobuf message that describes a .proto
source file or any element
therein. So a collection of descriptors can describe an entire schema of protobuf types, including
RPC services.
This repo was built to work with the original "V1" API of the Protobuf runtime for Go: github.com/golang/protobuf
.
Since the creation of this repo, a new runtime for Go has been release, a "V2" of the API in google.golang.org/protobuf
. Most protobuf users have likely upgraded to that newer runtime and thus likely encounter some interop issues using this repo. In the meantime, you can often work around these issues using the proto.MessageV1
and proto.MessageV2
converter functions (both are defined in the V1 proto
package).
We eventually want this repo to have much better interop with the V2 API. Here are the current goals:
- By EOY 2022: Update the
desc.Descriptor
type in this repo to be a wrapper around theprotoreflect.Descriptor
types in the V2 API. Also provide simple conversion functions to go from one to the other. This will likely resolve most of the issues that people encounter. - H1 2023: Create a new V2 of this whole repo. The V2 protobuf API now includes support for descriptors and dynamic messages, and it also exposes numerous low-level aspects like the binary wire format. So a lot of what's in this repo is no longer necessary. But some features still are, such as the
desc/builder
,desc/protoprint
,dynamic/grpcdynamic
,dynamic/msgregistry
, andgrpcreflect
packages. These will remain in the V2 form of the repo (though possibly rearranged a little). Noticeably absent from the list above isdesc/protoparse
, whose V2 API will be in a brand new module namedprotocompile
. It will be a much improved API, provide better performance, and directly use the reflection APIs in the v2 Protobuf runtime.
import "github.com/jhump/protoreflect/desc"
The desc
package herein introduces a Descriptor
interface and implementations of it that
correspond to each of the descriptor types. These new types are effectively smart wrappers around
the generated protobuf types
that make them much more useful and easier to use.
You can construct descriptors from file descriptor sets (which can be generated by protoc
), and
you can also load descriptors for messages and services that are linked into the current binary.
"What does it mean for messages and services to be linked in?" you may ask. It means your binary
imports a package that was generated by protoc
. When you generate Go code from your .proto
sources, the resulting package has descriptor information embedded in it. The desc
package allows
you to easily extract those embedded descriptors.
Descriptors can also be acquired directly from .proto
source files (using the protoparse
sub-package)
or by programmatically constructing them (using the builder
sub-package).
import "github.com/jhump/protoreflect/desc/protoparse"
The protoparse
package allows for parsing of .proto
source files into rich descriptors. Without
this package, you must invoke protoc
to either generate a file descriptor set file or to generate
Go code (which has descriptor information embedded in it). This package allows reading the source
directly without having to invoke protoc
.
import "github.com/jhump/protoreflect/desc/protoprint"
The protoprint
package allows for printing of descriptors to .proto
source files. This is
effectively the inverse of the protoparse
package. Combined with the builder
package, this
is a useful tool for programmatically generating protocol buffer sources.
import "github.com/jhump/protoreflect/desc/builder"
The builder
package allows for programmatic construction of rich descriptors. Descriptors can
be constructed programmatically by creating trees of descriptor protos and using the desc
package
to link those into rich descriptors. But constructing a valid tree of descriptor protos is far from
trivial.
So this package provides generous API to greatly simplify that task. It also allows for converting rich descriptors into builders, which means you can programmatically modify/tweak existing descriptors.
import "github.com/jhump/protoreflect/dynamic"
The dynamic
package provides a dynamic message implementation. It implements proto.Message
but
is backed by a message descriptor and a map of fields->values, instead of a generated struct. This
is useful for acting generically with protocol buffer messages, without having to generate and link
in Go code for every kind of message. This is particularly useful for general-purpose tools that
need to operate on arbitrary protocol buffer schemas. This is made possible by having the tools load
descriptors at runtime.
import "github.com/jhump/protoreflect/dynamic/grpcdynamic"
There is also sub-package named grpcdynamic
, which provides a dynamic stub implementation. The stub can
be used to issue RPC methods using method descriptors instead of generated client interfaces.
import "github.com/jhump/protoreflect/grpcreflect"
The grpcreflect
package provides an easy-to-use client for the
gRPC reflection service,
making it much easier to query for and work with the schemas of remote services.
It also provides some helper methods for querying for rich service descriptors for the services registered in a gRPC server.