This repository demonstrates two ways of using Go's new protobuf API to extend your protobufs and make them more powerful:
- Code generation at compile-time, with
protogen
— code in go/plugin/ - Reflection at runtime, with
protoreflect
— code in go/reflect/
This also demonstrates building protobufs with Bazel, which makes invoking protoc
(the protobuf compiler) a smooth part of the development workflow. See protos/ and BUILD.bazel
files throughout this repo for details.
Read more details about this in the corresponding blog post on eggybits.com.
Install Bazelisk
Set up bazelisk
:
# if on a Mac
brew tap bazelbuild/tap
brew install bazelisk
Verify that bazel
points to bazelisk
:
$ which bazel
/usr/local/bin/bazel
melinda at xmbp in ~/code/eggybytes/protobuf-two-ways on ml-add-readme*
$ ls -l /usr/local/bin/bazel
lrwxr-xr-x 1 melinda admin 34 Dec 2 11:33 /usr/local/bin/bazel -> ../Cellar/bazelisk/1.7.3/bin/bazel
To build every target defined in this repo with Bazel, run:
bazel build //...
To run every test target defined in this repo with Bazel (there's only one right now), run:
bazel test //...
In bazel-out/<your_architecture>/bin/protos/todo/todo_grpc_go_library_/protos/todo
, you'll find:
- todo.pb.go: standard protoc-gen-go output
- todo_grpc.pb.go: standard protoc-gen-grpc output
- todo.pb.custom.go: our custom code output
todo.pb.custom.go
should now look like:
package todo
import (
context "context"
mock "github.com/stretchr/testify/mock"
grpc "google.golang.org/grpc"
)
// ████
// ██░░░░██
// ██░░░░░░░░██
// ██░░░░░░░░██
// ██░░░░░░░░░░░░██
// ██░░ ░░░░ ░░██
// ██░░░░ ░░░░██
// ██░░░░░░░░██
// ████▓▓██
// MockEggDeliveryServiceClient is a mock EggDeliveryServiceClient which
// satisfies the EggDeliveryServiceClient interface.
type MockEggDeliveryServiceClient struct {
mock.Mock
}
func NewMockEggDeliveryServiceClient() *MockEggDeliveryServiceClient {
return &MockEggDeliveryServiceClient{}
}
func (c *MockEggDeliveryServiceClient) OrderEgg(ctx context.Context, in *OrderEggRequest, opts ...grpc.CallOption) (*OrderEggResponse, error) {
args := c.Called(ctx, in)
if args.Get(0) == nil {
return nil, args.Error(1)
}
return args.Get(0).(*OrderEggResponse), args.Error(1)
}