Skip to main content

15 Use remote packages

In this section, you'll learn how to use Buf's Go Module Proxy to import the Go/gRPC client and server stubs as you would import any other Go library. Remote packages thus reduces the code generation workflow to two steps:

  1. buf push
  2. go get (or go mod tidy)

15.1 Remove buf.gen.yaml#

You won't need to generate any code locally at this stage, so you can remove the buf.gen.yaml as well as the generated code in the gen directory:

rm buf.gen.yamlrm -rf gen

As expected, if you try to recompile your Go program, you'll notice a compilation error:

$ go build ./...
client/main.go:10:2: no required module provides package; to add it: go get

15.2 Depend on

You can depend on the same Go/gRPC client and server stubs by adapting our import paths to use the BSR Go module proxy.

The Go module path you need to use is derived from the name of the module you want to generate for and the name of the plugin you want to generate with:

With the module$BUF_USER/petapis and plugin, for example, the import path looks like this:$BUF_USER/petapis/grpc/go

Update your import paths accordingly:

 package main import (     "context"     "fmt"     "log"-    // This import path is based on the name declaration in the go.mod,-    // and the gen/proto/go output location in the buf.gen.yaml.-    petv1 ""+    petv1 "$BUF_USER/petapis/protocolbuffers/go/pet/v1"+    "$BUF_USER/petapis/grpc/go/pet/v1/petv1grpc"     "" )
 package main import (     "context"     "fmt"     "log"     "net"-    // This import path is based on the name declaration in the go.mod,-    // and the gen/proto/go output location in the buf.gen.yaml.-    petv1 ""+    petv1 "$BUF_USER/petapis/protocolbuffers/go/pet/v1"+    "$BUF_USER/petapis/grpc/go/pet/v1/petv1grpc"     "" )

Note, the gRPC generated code is output to a different package, so you'll need to modify the import and references to petv1grpc for the server/client stubs. The base types will remain importable from petv1.

Now if you run the command below, you'll notice that the remote package is successfully resolved:

$ go mod tidy
go: finding module for package$BUF_USER/petapis/protocolbuffers/go/pet/v1go: finding module for package$BUF_USER/petapis/grpc/go/pet/v1/petv1grpcgo: found$BUF_USER/petapis/grpc/go/pet/v1/petv1grpc in$BUF_USER/petapis/grpc/go v1.2.0-20220907172654-7abdb7802c8f.4go: found$BUF_USER/petapis/protocolbuffers/go/pet/v1 in$BUF_USER/petapis/protocolbuffers/go v1.28.1-20220907172654-7abdb7802c8f.4

The Go/gRPC client and server stubs are now included in your go.mod just like any other Go library.

15.3 Run the application#

You can run the application again to verify that the remote package works as expected.

First, start the server:

$ go run server/main.go
... Listening on

In a separate terminal, run the client and you'll see a successful PutPet operation:

$ go run client/main.go
... Connected to Successfully PutPet

You'll also notice this in the server logs (in the other terminal running the server):

$ go run server/main.go
... Listening on Got a request to create a PET_TYPE_SNAKE named Ekans

Everything works just as before, but you no longer have any locally generated code:

start/├──├── client│   └── main.go├── go.mod├── go.sum├── paymentapis│   ├── buf.lock│   ├── buf.yaml│   └── payment│       └── v1alpha1│           └── payment.proto├── petapis│   ├── buf.lock│   ├──│   ├── buf.yaml│   └── pet│       └── v1│           └── pet.proto└── server    └── main.go

15.4 Updating Versions#

When you update your module and push new commits, you can update your library version by incrementing the final element in the synthetic version (described above).

To demonstrate, make a small change by adding a comment to the PetStoreService:

$ cd petapis
+// PetStoreService defines a pet store service. service PetStoreService {   rpc GetPet(GetPetRequest) returns (GetPetResponse) {}   rpc PutPet(PutPetRequest) returns (PutPetResponse) {}   rpc DeletePet(DeletePetRequest) returns (DeletePetResponse) {}   rpc PurchasePet(PurchasePetRequest) returns (PurchasePetResponse) {} }

Push those changes:

$ buf push

Now edit your go.mod to use the latest version:

 module go 1.16 require (- v1.2.0-20210812172254-4514ddced058.4- v1.28.1-20210812172254-4514ddced058.4+ v1.2.0-20221114162513-4e6df5753af7.4+ v1.28.1-20221114162513-4e6df5753af7.4 v0.0.0-20210811021853-ddbe55d93216 // indirect v1.40.0 )

If you run the command below, you'll notice that your go.sum is updated with the version specified in your go.mod, using grpc/go as an example:

$ go mod tidy
- v1.2.0-20210812172254-4514ddced058.4 h1:QREnaHDWmv55R7nL3buUIRfHH9dSkmPXTenFz1LUUZ4=- v1.2.0-20210812172254-4514ddced058.4/go.mod h1:txlj4LYzQXieGG4fYs7419d7Mbh6Vp/32ZRkfZwaUMc=+ v1.2.0-20221114162513-4e6df5753af7.4 h1:lCa/8gUpxGfzYpd9gdkriJUd8YospXHonFySS9LkCzI=+ v1.2.0-20221114162513-4e6df5753af7.4/go.mod h1:RNC72B+4E2y6/h5H+SDM4J1VOdSiOPBzqCyr7kOdhvw=