The Buf Schema Registry provides remote packages for Golang: consume generated SDKs from modules and plugins using go get, just like any other Golang library.

This provides consumers of your API with generated SDKs on demand. With generated SDKs, you no longer need to generate code from Protobuf locally, and thus no longer need for consumers to pull in Protobuf files or perform any generation whatsoever.

The BSR Go module proxy implements the GOPROXY protocol for Buf modules by generating packages on the fly—Go code stubs aren't generated until you request them using go get. Once generated, they are cached, and the cached assets are returned from subsequent requests.

Using Go Modules

The key to consuming from the BSR Go module proxy is choosing the right Go module path. The import path for generated Go code has this format:

Go module path syntax
Examplebuf.build/gen/go/bufbuild/eliza/bufbuild/connect-go
Legend:
constant{variable}

In this example, buf.build/gen/go/bufbuild/eliza/bufbuild/connect-go, the BSR generates code for the bufbuild/eliza module using the bufbuild/connect-go. plugin. This package depends on buf.build/gen/go/bufbuild/eliza/protocolbuffers/go as well - connect-go has a dependency on code generated by the protocolbuffers/go plugin, and remote packages automatically include plugin dependencies!

Installing packages

To generate the bufbuild/eliza Protobuf module using the connect-go plugin, you could install the generated code like this:

$ go get buf.build/gen/go/bufbuild/eliza/bufbuild/connect-go
Output
go: downloading buf.build/gen/go/bufbuild/eliza/bufbuild/connect-go v1.1.0-20221108170037-30afbf7c670d.4 go: added buf.build/gen/go/bufbuild/eliza/bufbuild/connect-go v1.1.0-20221108170037-30afbf7c670d.4

You can use any plugin that generates Go, which can simplify Protobuf workflows down to two steps:

  1. buf push your module to the BSR.
  2. go get your generated Go module.

Versions

By default, when you go get a Buf module, the BSR generates code from the most recent reference for the module. But you can also install a specific module version using go get's @ syntax referencing an explicit version or a draft name.

Latest

Get the generated asset for the latest version of the module.

$ go get buf.build/gen/go/bufbuild/eliza/bufbuild/connect-go@latest

Commit

Get the generated asset for the module at a commit.

$ go get buf.build/gen/go/bufbuild/eliza/bufbuild/connect-go@dbde79169a014bd8b5bf8f89ac9b35c7

Tag

Get the generated asset for the module at a tag.

$ go get buf.build/gen/go/bufbuild/eliza/bufbuild/connect-go@foo

Draft

The BSR supports draft commits. This feature enables you to push unreleased Protobuf file changes and consume generated code without affecting the main branch.

$ buf push --draft dev-draft
$ go get buf.build/gen/go/bufbuild/eliza/bufbuild/connect-go@dev-draft
Caveats

References with names that contain / are not compatible with the Go remote packages versioning scheme.

Full Syntax

Go module version syntax
{pluginVersion}-{moduleTimestamp}-{moduleCommit}.{pluginRevision}
Examplev1.1.0-20221108170037-30afbf7c670d.4
Legend:
{variable}

With package versions (valid semver):

  • The version core is the plugin version 1.1.0
  • The semver pre-release version is composed of:
  • module commit timestamp (YYYYMMDDHHMMSS) 20221108170037
  • module commit short name (12 characters) 30afbf7c670d
  • The final identifier is the plugin revision 4 for the plugin version

Most users will likely use @latest, but if you need to reference a package version explicitly you can do so like this:

$ go get buf.build/gen/go/bufbuild/eliza/bufbuild/connect-go@v1.1.0-20221108170037-30afbf7c670d.4

Private modules

To generate Go code from private modules you'll need to make sure the Go tooling is correctly configured. Begin by logging into the BSR:

$ buf registry login

The go tool authenticates with proxies using .netrc credentials or credentials directly specified in GOPROXY URLs. You can use buf registry login to add BSR credentials to your .netrc file. You can obtain an API token (usable as netrc password) from the Settings page.

~/.netrc
machine buf.build
        login <USERNAME>
        password <TOKEN>

Or using direct credentials:

GOPROXY=https://$BSR_USER:$BSR_TOKEN@buf.build/gen/go

Like mentioned in the Go docs on using direct credentials: use caution when taking this approach as environment variables may appear in shell history and in logs.

Private modules are only accessible to authorized users and cannot be pulled through the default module proxy at https://proxy.golang.org or have their checksums verified with the public checksum database at https://sum.golang.org/. To access private modules you need to specify a combination of GOPROXY, GOPRIVATE, GONOPROXY and/or GONOSUMDB.

There are two possible ways to configure go for private modules:

  • Using GOPRIVATE=buf.build/gen/go. This implicitly sets GONOPROXY/GONOSUMDB to the same value, causing go to use the direct strategy for fetching directly from BSR without going through the public proxy.

    NOTE: Due to GONOPROXY including the buf registry, this is not compatible with specifying auth directly in GOPROXY. Only netrc based auth is supported in this configuration.

  • Using GOPROXY=https://buf.build/gen/go,$GOPROXY and GONOSUMDB=buf.build/gen/go. This instructs go to try a module from the buf from buf before falling back to the exisiting configured proxies. This works both for netrc and direct authentication.

Modify the Go environment using the export command in your shell or with the go env -w command to persist the change.

$ export GONOSUMDB=$GONOSUMDB,buf.build/gen/go

For more information, see the official private modules documentation.

Available plugins

For a full list of supported plugins navigate to the BSR plugins page and search for Go.

To learn more about how these plugins are packaged and distributed check out the bufbuild/plugins repository. If you find a useful plugin that should be added please file an issue!