Episode ini membawa file .proto menjadi kode nyata: instalasi plugin, perintah protoc untuk Go, implementasi server sederhana, implementasi client sederhana, lalu testing lokal dengan request-response yang berhasil dijalankan pertama kali.

Kontrak tanpa kode hanyalah dokumen. Episode 4 mengubah .proto kalian menjadi aplikasi yang benar-benar berjalan: membangkitkan kode dengan protoc, mengimplementasikan server, membuat client, dan melihat request-response pertama berhasil. Ini momen paling membangkitkan semangat dalam belajar gRPC — teori mulai menjadi nyata.
Kita memakai Go karena sintaksnya ringkas dan toolchain-nya sangat solid untuk gRPC. Prinsip yang sama berlaku untuk Node.js, Python, atau Java: kontrak sama, perintah protoc mirip, yang berbeda hanya plugin bahasa dan sintaks hasil generate.
Pastikan plugin Go terpasang seperti yang disiapkan di episode 0, lalu buat struktur project dan tarik dependency gRPC:
mkdir -p proto gen/catalog/v1
go get google.golang.org/grpc
go get google.golang.org/protobufStruktur proto/ menampung file .proto, dan gen/ menjadi lokasi output kode hasil generate. Perintah go get google.golang.org/grpc menarik runtime gRPC beserta dependency-nya ke go.mod.
Dengan plugin terpasang, bangkitkan kode dari kontrak product.proto di episode 3:
protoc -I proto \
--go_out=gen --go_opt=paths=source_relative \
--go-grpc_out=gen --go-grpc_opt=paths=source_relative \
proto/catalog/v1/product.protoPerintah protoc -I proto menyatakan root pencarian import. Setelah berjalan, dua file lahir di gen/catalog/v1/: product.pb.go berisi definisi message, dan product_grpc.pb.go berisi stub client serta antarmuka server.
Sekarang implementasikan antarmuka yang dibangkitkan. Buat file server/main.go:
package main
import (
"context"
"log"
"net"
"google.golang.org/grpc"
pb "learn-grpc/gen/catalog/v1"
)
type catalogServer struct {
pb.UnimplementedCatalogServiceServer
}
func (s *catalogServer) GetProduct(
ctx context.Context, in *pb.ProductId,
) (*pb.Product, error) {
return &pb.Product{
Id: in.Id,
Name: "Kursi Kantor",
Price: 450000,
}, nil
}
func main() {
lis, err := net.Listen("tcp", ":50051")
if err != nil {
log.Fatal(err)
}
s := grpc.NewServer()
pb.RegisterCatalogServiceServer(s, &catalogServer{})
log.Println("server listening di :50051")
if err := s.Serve(lis); err != nil {
log.Fatal(err)
}
}Ada tiga hal penting di sini: net.Listen("tcp", ":50051") membuka port 50051, pb.RegisterCatalogServiceServer mendaftarkan implementasi, dan s.Serve(lis) mulai melayani request. Embedding UnimplementedCatalogServiceServer membuat server tetap kompilasi walau ada method yang belum diimplementasi.
Dari sisi client, buat client/main.go yang memakai stub hasil generate:
package main
import (
"context"
"log"
"time"
"google.golang.org/grpc"
"google.golang.org/grpc/credentials/insecure"
pb "learn-grpc/gen/catalog/v1"
)
func main() {
conn, err := grpc.NewClient(
"localhost:50051",
grpc.WithTransportCredentials(insecure.NewCredentials()),
)
if err != nil {
log.Fatal(err)
}
defer conn.Close()
client := pb.NewCatalogServiceClient(conn)
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
res, err := client.GetProduct(ctx, &pb.ProductId{Id: "p-001"})
if err != nil {
log.Fatal(err)
}
log.Printf("produk: %s dengan harga %.0f", res.Name, res.Price)
}pb.NewCatalogServiceClient(conn) membuat stub yang siap dipakai, dan context.WithTimeout memberi batas waktu lima detik pada panggilan — pola deadline dari episode 2.
Jalankan server di satu terminal dan client di terminal lain:
go run ./serverSetelah log server muncul, dari terminal lain:
go run ./clientOutput client harus menampilkan produk: Kursi Kantor dengan harga 450000. Kalau kalian mendapat error connection refused, periksa apakah server benar-benar berjalan dan port 50051 tidak terblokir. Jalur go run ./client ini adalah ujung dari pipeline generate ke eksekusi — dari .proto sampai aplikasi berjalan.
Inti yang harus dibawa pulang:
protoc -I proto ... --go_out membangkitkan message; --go-grpc_out membangkitkan service.RegisterCatalogServiceServer dan berjalan di port 50051.Di episode 5 selanjutnya kita membahas unary, streaming, dan error handling dasar — implementasi keempat pola RPC yang dideklarasikan di episode 3, pemetaan status code ke skenario bisnis, rich error details, serta penanganan deadline dan cancelation di sisi client maupun server. Server-client pertama kalian akan bertransformasi menjadi layanan yang lengkap.