gRPC Services
Full gRPC server and client code generation with streaming support
Go support includes the complete Protocol Buffer ecosystem with all major plugins and performance optimizations. Perfect for microservices, CLI tools, and high-performance backend systems.
gRPC Services
Full gRPC server and client code generation with streaming support
HTTP/JSON APIs
REST API gateways via grpc-gateway or modern Connect protocol
High Performance
3.8x faster serialization with vtprotobuf optimization
Validation
Built-in message validation with CEL expressions
Essential Protocol Buffer Support
| Plugin | Description | Generated Files | Status |
|---|---|---|---|
| protoc-gen-go | Base message generation | *.pb.go | ✅ Stable |
| protoc-gen-go-grpc | gRPC services | *_grpc.pb.go | ✅ Stable |
| protoc-gen-connect-go | Connect protocol | *_connect.go | ✅ Modern |
| protoc-gen-grpc-gateway | HTTP/JSON gateway | *.pb.gw.go | ✅ Popular |
Message Validation
| Plugin | Description | Generated Files | Recommendation |
|---|---|---|---|
| protovalidate | Modern CEL validation | Runtime validation | ✨ Recommended |
| protoc-gen-validate | Legacy validation | *.pb.validate.go | ⚠️ Legacy |
Advanced Features
| Plugin | Description | Generated Files | Performance |
|---|---|---|---|
| protoc-gen-go-vtproto | Fast serialization | *_vtproto.pb.go | 3.8x faster |
| protoc-gen-go-json | JSON integration | *.pb.json.go | Fast JSON |
| protoc-gen-openapiv2 | OpenAPI v2 docs | *.swagger.json | API Docs |
| protoc-gen-grpc-federation | BFF generation | *_federation.pb.go | 🧪 Experimental |
languages.go = {enable = true;outputPath = "gen/go";packagePrefix = "github.com/myorg/myproject";options = [ "paths=source_relative" "require_unimplemented_servers=false"];};languages.go = {enable = true;outputPath = "gen/go";grpc = { enable = true; options = ["paths=source_relative"];};gateway = { enable = true; options = [ "paths=source_relative" "generate_unbound_methods=true" ];};};languages.go = {enable = true;outputPath = "gen/go";grpc.enable = true;protovalidate.enable = true;vtprotobuf = { enable = true; options = [ "paths=source_relative" "features=marshal+unmarshal+size+pool" ];};json = { enable = true; options = ["paths=source_relative"];};};languages.go = { enable = true; outputPath = "gen/go"; packagePrefix = "github.com/myorg/myproject"; options = ["paths=source_relative"];
# gRPC service generation grpc = { enable = true; options = [ "paths=source_relative" "require_unimplemented_servers=false" ]; };
# HTTP/JSON gateway for REST APIs gateway = { enable = true; options = [ "paths=source_relative" "generate_unbound_methods=true" "allow_delete_body=true" ]; };
# Modern validation (recommended) protovalidate = { enable = true; };
# Legacy validation validate = { enable = true; options = ["lang=go"]; };
# Modern Connect protocol connect = { enable = true; options = ["paths=source_relative"]; };
# High-performance serialization vtprotobuf = { enable = true; options = [ "paths=source_relative" "features=marshal+unmarshal+size+pool" ]; };
# JSON integration json = { enable = true; options = ["paths=source_relative" "orig_name=true"]; };
# OpenAPI documentation openapiv2 = { enable = true; options = ["logtostderr=true"]; };
# gRPC Federation (experimental) federation = { enable = true; options = ["paths=source_relative"]; };};Control exactly which proto files Go processes using files and additionalFiles:
Avoid Go Linting Issues
Problem: Go generates linting errors when processing Google API annotations.
Solution: Use files to exclude annotation files from Go while keeping them for other languages.
# Global files (used by all languages by default)protoc.files = ["./proto/common/v1/types.proto""./proto/common/v1/status.proto"];
languages = {# Go: Override global files - exclude Google annotationsgo = { enable = true; files = [ "./proto/common/v1/types.proto" "./proto/common/v1/status.proto" "./proto/internal/v1/user_service.proto" # NOTE: No Google API annotations - prevents linting errors ]; grpc.enable = true;};
# JavaScript: Extend global files - include Google annotationsjs = { enable = true; additionalFiles = [ "./proto/api/v1/user_api.proto" "./proto/google/api/annotations.proto" # Needed for REST mapping "./proto/google/api/http.proto" ]; es.enable = true;};};Internal Services
Generate Go code only for backend-specific services:
languages.go = {enable = true;outputPath = "internal/proto/go";# Override: Only internal services + shared typesfiles = [ "./proto/common/v1/types.proto" "./proto/internal/v1/user_service.proto" "./proto/internal/v1/admin_service.proto" "./proto/internal/v1/metrics_service.proto" # No public API files - backend only];grpc.enable = true;protovalidate.enable = true;};Add Go-Specific Files
Extend global files with Go-specific protobuf definitions:
languages.go = {enable = true;# Use global files + these additional Go-specific filesadditionalFiles = [ "./proto/go/v1/go_extensions.proto" "./proto/monitoring/v1/metrics.proto" "./proto/internal/v1/background_jobs.proto"];grpc.enable = true;vtprotobuf.enable = true;};| Option | Type | Description | Example |
|---|---|---|---|
files | list | Override global files completely | Backend-only services |
additionalFiles | list | Extend global files | Add monitoring protos |
Exclude Google Annotations
Use files to prevent Go linting errors from Google API annotations
Backend Services Only
Generate only internal gRPC services for Go backends
Add Monitoring
Include Go-specific metrics and health check protos
Multi-Team Projects
Different teams can process different proto subsets
Use Buf registry plugins directly:
languages.go = { enable = true; plugins = [ "buf.build/protocolbuffers/go" "buf.build/grpc/go" { plugin = "buf.build/community/planetscale-vtprotobuf"; opt = ["features=marshal+unmarshal+size+pool"]; } "buf.build/community/mfridman-go-json" "buf.build/bufbuild/validate-go" ];};syntax = "proto3";
package user.v1;
option go_package = "github.com/myorg/myproject/gen/go/user/v1;userv1";
import "validate/validate.proto";import "google/api/annotations.proto";
message User { string id = 1; string name = 2 [(validate.rules).string = {min_len: 1, max_len: 100}]; string email = 3 [(validate.rules).string.email = true]; int32 age = 4 [(validate.rules).int32 = {gte: 0, lte: 150}]; repeated string roles = 5; UserStatus status = 6; repeated Address addresses = 7;
message Address { string street = 1; string city = 2; string state = 3; string zip = 4; string country = 5; }}
enum UserStatus { USER_STATUS_UNSPECIFIED = 0; USER_STATUS_ACTIVE = 1; USER_STATUS_INACTIVE = 2; USER_STATUS_SUSPENDED = 3;}
service UserService { rpc CreateUser(CreateUserRequest) returns (CreateUserResponse) { option (google.api.http) = { post: "/v1/users" body: "user" }; }
rpc GetUser(GetUserRequest) returns (GetUserResponse) { option (google.api.http) = { get: "/v1/users/{user_id}" }; }}
message CreateUserRequest { User user = 1;}
message CreateUserResponse { User user = 1;}
message GetUserRequest { string user_id = 1;}
message GetUserResponse { User user = 1;}package main
import ( "context" "log" "net"
"google.golang.org/grpc" pb "github.com/myorg/myproject/gen/go/user/v1")
type server struct { pb.UnimplementedUserServiceServer users map[string]*pb.User}
func (s *server) CreateUser(ctx context.Context, req *pb.CreateUserRequest) (*pb.CreateUserResponse, error) { user := req.GetUser()
// Validation happens automatically if validate plugin is enabled if err := user.Validate(); err != nil { return nil, err }
s.users[user.GetId()] = user return &pb.CreateUserResponse{User: user}, nil}
func (s *server) GetUser(ctx context.Context, req *pb.GetUserRequest) (*pb.GetUserResponse, error) { user, exists := s.users[req.GetUserId()] if !exists { return nil, status.Error(codes.NotFound, "user not found") } return &pb.GetUserResponse{User: user}, nil}
func main() { lis, err := net.Listen("tcp", ":50051") if err != nil { log.Fatalf("failed to listen: %v", err) }
s := grpc.NewServer() pb.RegisterUserServiceServer(s, &server{ users: make(map[string]*pb.User), })
log.Println("Server listening on :50051") if err := s.Serve(lis); err != nil { log.Fatalf("failed to serve: %v", err) }}package main
import ( "context" "log" "net/http"
"connectrpc.com/connect" pb "github.com/myorg/myproject/gen/go/user/v1" "github.com/myorg/myproject/gen/go/user/v1/userv1connect")
type server struct { users map[string]*pb.User}
func (s *server) CreateUser( ctx context.Context, req *connect.Request[pb.CreateUserRequest],) (*connect.Response[pb.CreateUserResponse], error) { user := req.Msg.GetUser() s.users[user.GetId()] = user
return connect.NewResponse(&pb.CreateUserResponse{ User: user, }), nil}
func (s *server) GetUser( ctx context.Context, req *connect.Request[pb.GetUserRequest],) (*connect.Response[pb.GetUserResponse], error) { user, exists := s.users[req.Msg.GetUserId()] if !exists { return nil, connect.NewError(connect.CodeNotFound, errors.New("user not found")) }
return connect.NewResponse(&pb.GetUserResponse{ User: user, }), nil}
func main() { srv := &server{users: make(map[string]*pb.User)}
mux := http.NewServeMux() path, handler := userv1connect.NewUserServiceHandler(srv) mux.Handle(path, handler)
log.Println("Connect server listening on :8080") http.ListenAndServe(":8080", mux)}package main
import ( "context" "log" "net" "net/http"
"github.com/grpc-ecosystem/grpc-gateway/v2/runtime" "google.golang.org/grpc" pb "github.com/myorg/myproject/gen/go/user/v1")
func main() { // Start gRPC server go func() { lis, _ := net.Listen("tcp", ":50051") s := grpc.NewServer() pb.RegisterUserServiceServer(s, &server{ users: make(map[string]*pb.User), }) s.Serve(lis) }()
// Start HTTP gateway ctx := context.Background() mux := runtime.NewServeMux() opts := []grpc.DialOption{grpc.WithInsecure()}
err := pb.RegisterUserServiceHandlerFromEndpoint(ctx, mux, "localhost:50051", opts) if err != nil { log.Fatal(err) }
log.Println("HTTP gateway listening on :8080") http.ListenAndServe(":8080", mux)}package main
import ( "context" "log" "time"
"google.golang.org/grpc" "google.golang.org/grpc/credentials/insecure" pb "github.com/myorg/myproject/gen/go/user/v1")
func main() { conn, err := grpc.NewClient("localhost:50051", grpc.WithTransportCredentials(insecure.NewCredentials())) if err != nil { log.Fatal(err) } defer conn.Close()
client := pb.NewUserServiceClient(conn) ctx, cancel := context.WithTimeout(context.Background(), time.Second) defer cancel()
// Create user createResp, err := client.CreateUser(ctx, &pb.CreateUserRequest{ User: &pb.User{ Id: "123", Name: "John Doe", Email: "john@example.com", Age: 30, Roles: []string{"user", "admin"}, Status: pb.UserStatus_USER_STATUS_ACTIVE, }, }) if err != nil { log.Fatal(err) } log.Printf("Created user: %v", createResp.GetUser())
// Get user getResp, err := client.GetUser(ctx, &pb.GetUserRequest{ UserId: "123", }) if err != nil { log.Fatal(err) } log.Printf("Retrieved user: %v", getResp.GetUser())}Enable vtprotobuf for 3.8x faster serialization:
languages.go = { enable = true; vtprotobuf = { enable = true; options = [ "paths=source_relative" "features=marshal+unmarshal+size+pool" ]; };};Usage:
// Fast marshalingdata, err := user.MarshalVT()
// Fast unmarshalingvar user pb.Usererr := user.UnmarshalVT(data)
// Object poolinguser := pb.UserFromVTPool()defer user.ReturnToVTPool()paths=source_relative for cleaner importsfiles to exclude Google API annotations and prevent Go linting errorscd examples/simple-flakenix developgo run main.goIf you see import errors, ensure your packagePrefix matches your Go module path:
languages.go = { packagePrefix = "github.com/yourusername/yourproject";};Some plugins aren’t yet in nixpkgs. Provide custom packages:
languages.go = { vtprotobuf.package = pkgs.buildGoModule { ... };};{ inputs = { nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable"; flake-utils.url = "github:numtide/flake-utils"; bufrnix = { url = "github:conneroisu/bufrnix"; inputs.nixpkgs.follows = "nixpkgs"; }; };
outputs = { nixpkgs, flake-utils, bufrnix, ... }: flake-utils.lib.eachDefaultSystem ( system: let pkgs = import nixpkgs {inherit system;}; in { devShells.default = pkgs.mkShell { packages = with pkgs; [ go protobuf protoc-gen-go protoc-gen-go-grpc buf ]; };
packages = { default = bufrnix.lib.mkBufrnixPackage { inherit pkgs; config = { root = "."; protoc = { includeDirectories = ["proto"]; files = ["proto/example/v1/user.proto"]; };
languages = { go = { enable = true; outputPath = "proto/gen/go";
# Per-language file control (new feature) # files = [ # "./proto/common/v1/types.proto" # "./proto/internal/v1/user_service.proto" # # Note: Exclude Google API annotations to prevent Go linting errors # ]; # additionalFiles = [ # "./proto/monitoring/v1/metrics.proto" # ];
# gRPC support grpc.enable = true;
# OpenAPI v2 generation openapiv2 = { enable = true; outputPath = "proto/gen/openapi"; };
# High-performance vtprotobuf plugin vtprotobuf = { enable = true; options = [ "paths=source_relative" "features=marshal+unmarshal+size+pool" ]; };
# JSON marshaling support json.enable = true; }; }; }; }; }; } );}