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

12 Building Your First gRPC Client

IH
Ihsan Arif
Writer at Santekno · Backend Engineer

In the modern software development ecosystem, inter-service communication is the backbone of microservices architecture. One of the most popular and efficient RPC (Remote Procedure Call) protocols, developed by Google, is gRPC. This protocol has become the de facto standard for communication between backend services in many organizations. However, understanding and implementing your first gRPC client can be a challenge in itself if you aren’t guided systematically.

In this article, I’ll walk you through the process of building your first gRPC client: from generating the stub code, to building the client application code, all the way to performing real communication with a server. I’ll also include code examples, simulations, comparison tables, and an end-to-end flow diagram.

What Is gRPC?

Before we move into the practical stage, let’s briefly review what gRPC is and why it’s so popular.

gRPC is a modern RPC framework that uses Protobuf (Protocol Buffers) as its data serialization format. Its advantages include:

  • High performance (HTTP/2)
  • Clear API definitions via .proto files
  • Cross-platform and cross-language support
  • Mature documentation and a robust tooling ecosystem

Initial Preparation

Before building the client, make sure you’ve completed the following:

  • A gRPC server is already running (or you at least have its .proto file)
  • protoc — the Protobuf compiler — is installed
  • The gRPC plugin for your programming language of choice is available (in this article: Go, which is popular and easy to follow)

The basic directory structure of the project will look like this:

text
1grpc-demo/
2├── proto/
3│   └── hello.proto
4├── server/
5│   └── main.go
6└── client/
7    └── main.go

Defining the API with .proto

Let’s say we have a simple API: the client asks the server to return a greeting. Create the following proto/hello.proto file:

proto
 1syntax = "proto3";
 2
 3package hello;
 4
 5service Greeter {
 6  rpc SayHello (HelloRequest) returns (HelloReply) {}
 7}
 8
 9message HelloRequest {
10  string name = 1;
11}
12
13message HelloReply {
14  string message = 1;
15}

Generating the Stub Code

Run the following command from the project root to generate the gRPC code for Go:

bash
1protoc --go_out=. --go-grpc_out=. proto/hello.proto

This will generate Go files in the proto/ folder. They contain both the client and server interfaces.


Steps to Build a gRPC Client

1. The Communication Flow Concept

How does a gRPC client work? Let’s take a look at the following diagram:

MERMAID
sequenceDiagram
    participant Client
    participant Stub
    participant Server
    Client->>Stub: Memanggil stub local (SayHello)
    Stub->>Server: Membuat dan mengirim request (HelloRequest)
    Server->>Stub: Mengembalikan response (HelloReply)
    Stub->>Client: Mengembalikan nilai (HelloReply)

The client stub acts as a “local proxy,” so calling a remote function is as easy as calling a local method.


2. Writing the Client Code

Open client/main.go and write the following code:

go
 1package main
 2
 3import (
 4    "context"
 5    "log"
 6    "os"
 7    "time"
 8
 9    "google.golang.org/grpc"
10    pb "grpc-demo/proto"     // Import the generated .proto code
11)
12
13const (
14    address     = "localhost:50051"
15    defaultName = "dunia"
16)
17
18func main() {
19    conn, err := grpc.Dial(address, grpc.WithInsecure(), grpc.WithBlock())
20    if err != nil {
21        log.Fatalf("gagal koneksi: %v", err)
22    }
23    defer conn.Close()
24    c := pb.NewGreeterClient(conn)
25
26    name := defaultName
27    if len(os.Args) > 1 {
28        name = os.Args[1]
29    }
30
31    ctx, cancel := context.WithTimeout(context.Background(), time.Second)
32    defer cancel()
33
34    r, err := c.SayHello(ctx, &pb.HelloRequest{Name: name})
35    if err != nil {
36        log.Fatalf("gagal greeting: %v", err)
37    }
38    log.Printf("Salam: %s", r.GetMessage())
39}

A breakdown of the steps:

  • Create the connection: grpc.Dial
  • Create the client object: NewGreeterClient
  • Set the timeout and context
  • Call the RPC: SayHello
  • Receive the response from the server

3. Simulating the Client-Server Interaction

Let’s simulate the code path involved:

StepObjectFunctionInfo/Data
1. Connectiongrpc.ConnDial(address)Opens an HTTP/2 channel to Srv
2. StubGreeterClientNewGreeterClient()Instantiates the client playground
3. RequestClientSayHello(ctx, req)Sends HelloRequest{Name}
4. ResponseServerSayHello()Returns HelloReply{Message}
5. OutputClientReceives the responsePrint message / handle error


Common Challenges When Building a gRPC Client

1. Protobuf Path Errors

Make sure the import path is correct. For Go, you typically use:

go
1pb "grpc-demo/proto"

2. TLS vs Insecure

During development, you can use grpc.WithInsecure(), but in production you MUST use TLS for security.

3. Timeout & Context

The context lets you set a timeout and cancel an RPC activity if the response takes too long.


Example Output

If your server is running and you execute:

bash
1go run client/main.go Dunia

Then the output will look like this:

text
12024/07/01 Salam: Halo Dunia

Comparing the gRPC Client with a REST Client

Here’s a concise table summarizing the advantages of a gRPC client over REST:

FeaturegRPCREST
Data FormatProtobuf (binary, compact)JSON (plain)
PerformanceHigh (HTTP/2)Tends to be lower
Type SafetyYesNo (JSON)
StreamingYes (bi-directional)Limited
Auto CodegenStrong (protoc)Manual
SecurityTLS/Mutual TLSPossible


Client Debugging Tips

  • Use grpclog.SetLoggerV2 for verbose debugging
  • Check the port and service registry if you encounter a connection refused error
  • A mismatch in the Protobuf definitions between client and server will cause an Unimplemented error

Starting the Server (For Testing)

Make sure a server is running on localhost:50051. Here’s an example of a simple service:

go
 1package main
 2
 3import (
 4    "context"
 5    "log"
 6    "net"
 7
 8    "google.golang.org/grpc"
 9    pb "grpc-demo/proto"
10)
11
12type server struct {
13    pb.UnimplementedGreeterServer
14}
15
16func (s *server) SayHello(ctx context.Context, in *pb.HelloRequest) (*pb.HelloReply, error) {
17    return &pb.HelloReply{Message: "Halo " + in.GetName()}, nil
18}
19
20func main() {
21    lis, err := net.Listen("tcp", ":50051")
22    if err != nil {
23        log.Fatalf("failed to listen: %v", err)
24    }
25    grpcServer := grpc.NewServer()
26    pb.RegisterGreeterServer(grpcServer, &server{})
27    log.Println("Server berjalan di :50051...")
28    grpcServer.Serve(lis)
29}

Conclusion

Building your first gRPC client is an important milestone for any modern engineer, especially those working with microservices. With its efficient protocol, built-in type safety, and automated code generation tooling, building a gRPC client is almost as easy as using a regular HTTP client—but with performance, security, and scalability far above average. Once you understand the role of the .proto file, the stub, and the RPC execution order, you’re ready to explore advanced features such as streaming, error handling, and interceptors in gRPC.

Good luck building your first gRPC client — and welcome to the world of professional distributed systems!

Related Articles

💬 Comments