Skip to main content

Go

Breaking changes

Remote code generation for Go is currently in alpha. Although you're free to experiment with it, be aware that Buf may introduce breaking changes that could impact your workflows.

The Buf Schema Registry (BSR) supports remote code generation for Go. With this feature, you can push Buf modules to the BSR and go get Go code stubs generated from those Protobuf definitions—without ever needing to generate code on your own. Go source code generated by the BSR is hosted on the BSR's Go module proxy.

With this feature, you no longer need to maintain Protobuf files or runtime dependencies like [protoc] plugins—in fact, JavaScript and TypeScript developers can avoid local code generation altogether for any Buf modules that have been pushed to the BSR.

This feature is especially useful for creating API clients for Go, as it provides consumers of your API with generated Go SDKs on demand. With remote generation, you no longer need to generate Go code from Protobuf locally, and thus no longer need to maintain Protobuf files or protoc-based plugins.

BSR Go module proxy#

The BSR Go module proxy implements the GOPROXY protocol for Buf modules by generating assets on the fly—Go code stubs aren't generated until you request them using go get.

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:

Generated Go module path syntax
Examplego.buf.build/grpc/go/bufbuild/eliza
Legend:constant{variable}

So if you wanted to, for example, generate the acme/paymentapis Protobuf module using the grpc/go template, you could install the generated code like this:

$ go get go.buf.build/grpc/go/acme/paymentapis

You can use any template 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

Try it out!#

In this example, we'll use the Go gRPC client for the Eliza demo service. Since this is a gRPC/Protobuf API we get a generated client SDK with minimal effort. The grpc/go template is used to generate the bufbuild/eliza module.

See the above for a refresher on Go module import paths.

package main
import (    "context"    "crypto/tls"    "log"
    // Import the Eliza API definitions and generate using the template grpc/go.    elizav1 "go.buf.build/grpc/go/bufbuild/eliza/buf/connect/demo/eliza/v1"    "google.golang.org/grpc"    "google.golang.org/grpc/credentials")
func main() {    cc, err := grpc.Dial(        "demo.connect.build:443",        grpc.WithTransportCredentials(credentials.NewTLS(&tls.Config{})),    )    if err != nil {        log.Fatalf("Failed to dial GCS API: %v", err)    }    client := elizav1.NewElizaServiceClient(cc)    resp, err := client.Say(context.Background(), &elizav1.SayRequest{        Sentence: "Hello remote generation",    })    if err != nil {        log.Fatalf("Failed to get bucket: %v", err)    }    log.Println(resp)}

If you're using Go modules you'll observe a version such as v1.4.6 in the go.mod file. To better understand versioning, see the synthetic versions documentation.

go.mod
require (    go.buf.build/grpc/go/bufbuild/eliza v1.4.6)

Generate private modules#

To generate Go code from private modules you'll need to make sure the Go tooling is correctly configured.

  1. Log into the BSR:

    The go tool uses .netrc credentials if available and you can use buf registry login to add this to your .netrc file. You can obtain an API token (password) from the Settings page.

    $ buf registry login
    ~/.netrc
    machine buf.build        login <USERNAME>        password <TOKEN>machine go.buf.build        login <USERNAME>        password <TOKEN>
  2. Go Environment Configuration

    The GOPRIVATE environment variable controls which modules the go command considers to be private and thus shouldn't use the proxy or checksum database. This is important since you don't want to send private information to the default Go module proxy at https://proxy.golang.org.

    Set this environment variable:

    $ export GOPRIVATE=go.buf.build

    If you already have GONOSUMDB configured, you also need to add go.buf.build to it:

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

    This isn't necessary if you do not already have GONOSUMDB configured, as GOPRIVATE automatically sets it in this case.

    For more information, see the official private modules documentation.