Skip to content
Santekno.com | Tech Tutorials and Trends
EN
📖 0%
17 Jun 2025 · 5 min read ·Article 9 / 110
Go

9 Generating Go Code from a Protobuf File

IH
Ihsan Arif
Writer at Santekno · Backend Engineer

Google Protocol Buffers (protobuf) has become one of the most popular serialization standards in the world of backend services. One of protobuf’s greatest strengths is its ability to generate code in a wide range of languages, including Go. In this chapter, we will take a detailed look at how to generate Go code from a .proto file, walk through its workflow, and share practical tips so that the process runs without a hitch.


Why Protobuf for Go?

Before diving into the technical details, it is important to understand the reasoning behind using protobuf in the Go world. Protobuf offers data serialization that is compact, type-safe, and high-performance. When we want to build microservices that communicate over gRPC within the Go ecosystem, protobuf + Go is a match made in heaven.


The Workflow for Generating Go Code from Protobuf

Let’s trace the main flow of generating Go code from a proto file using protoc.

MERMAID
flowchart TD
    A[Menulis File proto] --> B[Menjalankan Protoc Compiler]
    B --> C[Protoc Go Plugin]
    C --> D[Menghasilkan File .pb.go]

Steps:

  1. We write the schema definition in a .proto file
  2. We run the protoc compiler, equipped with the Go plugin
  3. The protoc plugin transforms the .proto file into a .pb.go file that is ready to use in Go code

1. Preparing the Environment

Make sure our environment supports the following process:

Tool/LibraryMinimum VersionPurposeInstall Command
Go1.20+Primary languagego.dev/dl
Protobuf3.0+.proto compilerDownload Binaries
protoc-gen-go1.27+Go code generation plugingo install google.golang.org/protobuf/cmd/protoc-gen-go@latest
protoc-gen-go-grpc1.2+Go gRPC code generationgo install google.golang.org/grpc/cmd/protoc-gen-go-grpc@latest

Danger
Tip:
Make sure GOPATH/bin is in your $PATH so that executables like protoc-gen-go can be recognized when running protoc.

2. Example .proto File Definition

Let’s start with a simple proto file example, user.proto, representing a user management service:

protobuf
 1syntax = "proto3";
 2
 3package user;
 4
 5option go_package = "github.com/example/proto/userpb;userpb";
 6
 7message User {
 8  int64 id = 1;
 9  string name = 2;
10  string email = 3;
11}
12
13service UserService {
14  rpc GetUser(GetUserRequest) returns (User);
15}
16
17message GetUserRequest {
18  int64 id = 1;
19}

Explanation:

  • option go_package defines the Go import path and the name of the package that will be generated.
  • There is one service, UserService, with a GetUser method.

3. Generating the Go Code

Once the proto file is ready, it’s time to run protoc with the Go plugin. Let’s assume our proto file is located in the proto/ folder.

a) Generate the Data Structures

bash
1protoc --go_out=. --go_opt=paths=source_relative proto/user.proto
  • --go_out=. means the generated file (user.pb.go) will be placed in the current directory.
  • --go_opt=paths=source_relative keeps the folder structure the same as the input.

b) Generate the gRPC Code (Optional)

If there is a service (such as UserService), we will also want to generate its stub code:

bash
1protoc --go-grpc_out=. --go-grpc_opt=paths=source_relative proto/user.proto

Afterwards, two files will appear:

File NamePurpose
user.pb.goData structs, serialization logic
user_grpc.pb.gogRPC stub/service interface


4. Simulating Use of the Generated Files

Let’s simulate using the generated files in a Go application.

a) Import and Instantiate the Struct

go
 1package main
 2
 3import (
 4    "fmt"
 5    userpb "github.com/example/proto/userpb"
 6)
 7
 8func main() {
 9    user := &userpb.User{
10        Id:    1,
11        Name:  "Andi",
12        Email: "andi@mail.com",
13    }
14    fmt.Printf("User: %+v\n", user)
15}

b) gRPC Server Handler Example

We can also directly implement a gRPC server from the generated code:

go
 1type server struct {
 2    userpb.UnimplementedUserServiceServer
 3}
 4
 5func (s *server) GetUser(ctx context.Context, req *userpb.GetUserRequest) (*userpb.User, error) {
 6    // Typically fetch the user data from the DB
 7    return &userpb.User{
 8        Id:     req.GetId(),
 9        Name:   "Andi",
10        Email:  "andi@mail.com",
11    }, nil
12}

5. Troubleshooting: Common Errors During Generation

Error MessageCauseSolution
protoc-gen-go: program not found or is not executablePlugin not installedRun go install ... and check $PATH
option go_package is requiredThe go_package option is missingAdd option go_package to the .proto file
cannot find package ...Import structure doesn’t matchStay consistent with go_package and $GOPATH

6. Productivity Tips

  • Save the generated files into a internal/pb/ subfolder to keep them isolated.
  • Add them to .gitignore if your build pipeline always regenerates them.
  • Update the plugins regularly, since the protobuf Go ecosystem is updated fairly often.

Automation Example

To be more productive, save the generation script into a Makefile:

makefile
1PROTO_DIR=proto
2OUT_DIR=internal/pb
3
4gen-proto:
5	protoc --go_out=$(OUT_DIR) --go_opt=paths=source_relative \
6	       --go-grpc_out=$(OUT_DIR) --go-grpc_opt=paths=source_relative \
7	       $(PROTO_DIR)/*.proto

7. Conclusion

Generating Go code from a Protobuf file is actually straightforward: write the schema, run protoc with the Go plugin, and use the result. Still, it pays to understand the workflow and the best practices so that the process is efficient, consistent, and trouble-free.

Protobuf + Go can serve as a strong foundation for modern microservices. With a solid grasp of code generation, your pipeline will become more reliable and future-proof.


Have fun exploring! 🚀
Don’t hesitate to share your experiences or ask questions if you run into an interesting error while using protobuf in Go.

Related Articles

💬 Comments