tutorial

Struktur Kode Otomatis yang Dihasilkan oleh protoc

Ketika kamu menulis file .proto, kamu sedang mendeskripsikan kontrak komunikasi yang kuat, lintas bahasa, dan terstandarisasi. Tapi apa sebenarnya yang terjadi ketika kamu menjalankan perintah protoc di Go? Artikel ini akan membedah struktur kode otomatis yang dihasilkan oleh protoc, menjelaskan apa saja yang dibuat, dan bagaimana kita bisa menggunakannya secara efisien dalam project gRPC menggunakan bahasa Go.


Apa Itu protoc dan Plugin-nya?

protoc adalah compiler untuk Protocol Buffers yang membaca file .proto dan menghasilkan kode dalam bahasa pemrograman pilihan, termasuk Go. Agar bisa digunakan untuk gRPC, kita butuh dua plugin penting:

  • protoc-gen-go untuk menghasilkan struktur data (message)
  • protoc-gen-go-grpc untuk menghasilkan service stub (client/server)

Contoh perintah generate:

protoc \
  --go_out=. \
  --go-grpc_out=. \
  api/user.proto

Hasil dari perintah ini adalah dua file:

user.pb.go
user_grpc.pb.go

Struktur File Otomatis: Apa Isinya?

Mari kita bedah satu per satu isi dari file hasil generate ini.


📁 user.pb.go: Representasi Data (Message)

File ini berisi definisi struct Go yang mewakili message dari .proto.

Contoh:

message User {
  string id = 1;
  string name = 2;
}

Hasil generate-nya:

type User struct {
  Id   string `protobuf:"bytes,1,opt,name=id,proto3"`
  Name string `protobuf:"bytes,2,opt,name=name,proto3"`
}

Juga termasuk:

  • Fungsi marshal/unmarshal Protobuf
  • Getter/Setter (jika menggunakan opsi tertentu)
  • Metadata protobuf internal

File ini fokus pada representasi data, bukan logika bisnis.


📁 user_grpc.pb.go: Client & Server Interface

File ini fokus pada aspek komunikasi antar service.

Contoh service:

service UserService {
  rpc GetUser(GetUserRequest) returns (UserResponse);
}

Hasil generate-nya:

type UserServiceClient interface {
  GetUser(ctx context.Context, in *GetUserRequest, opts ...grpc.CallOption) (*UserResponse, error)
}

type UserServiceServer interface {
  GetUser(context.Context, *GetUserRequest) (*UserResponse, error)
}

Juga disediakan fungsi untuk mendaftarkan server:

func RegisterUserServiceServer(s *grpc.Server, srv UserServiceServer)

Dan fungsi client helper:

func NewUserServiceClient(cc grpc.ClientConnInterface) UserServiceClient

Diagram Struktur (Visualisasi Mermaid)

Agar makin mudah dipahami, berikut diagram visualisasi hasil generate dengan mermaid:

flowchart TB
  A[".proto File"] -->|protoc| B[user.pb.go]
  A -->|protoc| C[user_grpc.pb.go]

  B --> D[Struct Message (User, Request, Response)]
  C --> E[Interface Server & Client]
  C --> F[Fungsi Register gRPC Service]

Kenapa Penting Memahami Struktur Ini?

Jika kamu ingin membangun aplikasi skala besar, kamu akan sering:

  • Men-debug komunikasi antar service
  • Membuat unit test client/server
  • Mengatur package dan import path yang sesuai
  • Refactor ketika kontrak .proto berubah

Dengan memahami struktur otomatis ini, kamu bisa:

✅ Lebih cepat memahami flow komunikasi ✅ Menyesuaikan arsitektur project ✅ Menghindari error import & duplicate symbol


✅ Makefile untuk Generate Otomatis

Tambahkan file Makefile di root proyek kamu:

PROTO_DIR=proto
GEN_DIR=gen

PROTO_FILES=$(wildcard $(PROTO_DIR)/*.proto)

generate:
	@mkdir -p $(GEN_DIR)
	@for file in $(PROTO_FILES); do \
		protoc \
			--go_out=$(GEN_DIR) \
			--go-grpc_out=$(GEN_DIR) \
			--go_opt=paths=source_relative \
			--go-grpc_opt=paths=source_relative \
			$$file; \
	done

clean:
	rm -rf $(GEN_DIR)/*.pb.go

🛠 Jalankan dengan:

make generate

✅ Struktur Folder Modular

Gunakan struktur ini agar rapi dan scalable untuk proyek besar:

your-project/
├── Makefile
├── go.mod
├── proto/
│   ├── user.proto
│   └── product.proto
├── gen/
│   ├── user/
│   │   ├── user.pb.go
│   │   └── user_grpc.pb.go
│   └── product/
│       ├── product.pb.go
│       └── product_grpc.pb.go
├── internal/
│   ├── server/
│   └── client/

Tips:

  • Simpan .proto di direktori proto/
  • Output ke gen/<modul> agar tidak bercampur
  • Gunakan package Go sesuai folder agar import bersih

✅ Bash Script untuk Multi .proto

Jika kamu tidak ingin pakai Makefile, bisa pakai bash script:

scripts/gen.sh

#!/bin/bash

PROTO_DIR=proto
GEN_DIR=gen

mkdir -p $GEN_DIR

for file in $PROTO_DIR/*.proto; do
  filename=$(basename "$file")
  filename_no_ext="${filename%.*}"

  mkdir -p $GEN_DIR/$filename_no_ext

  protoc \
    --go_out=$GEN_DIR/$filename_no_ext \
    --go-grpc_out=$GEN_DIR/$filename_no_ext \
    --go_opt=paths=source_relative \
    --go-grpc_opt=paths=source_relative \
    $file
done

echo "✅ Protobuf files generated successfully."

💡 Jangan lupa:

chmod +x scripts/gen.sh
./scripts/gen.sh

Kesimpulan

File hasil generate dari protoc bukanlah magic. Mereka adalah representasi konkret dari definisi .proto yang kamu buat — dikompilasi menjadi kode Go yang siap pakai untuk komunikasi gRPC. Memahami struktur dan isi dari file pb.go dan grpc.pb.go sangat penting bagi kamu yang ingin serius mengadopsi arsitektur berbasis microservice atau API yang scalable.

Berikut adalah tiga tambahan praktikal yang bisa langsung kamu sertakan di akhir artikel atau dijadikan artikel lanjutan. Semua ini dirancang agar workflow gRPC kamu lebih modular, maintainable, dan otomatis.


comments powered by Disqus