
Building a gRPC Client in Go
Introduction
In this article, we will build a gRPC client in Go from the same Protocol Buffers contract as the Go gRPC server. We will generate the client stub, create a reusable gRPC channel, set a deadline, and call the unary GetBookList RPC.
The example uses plaintext transport so it is easy to run locally. That is a development choice, not a production default.
Plan
The plan for this article is as follows.
- Scaffold the client-side stubs and Go module.
- Implement the gRPC client.
- Communicate with the server.
In a nutshell, we will be generating the client for the server we built in our previous post.

In the above diagram, we will look at how to achieve the components on the left side.
💡 As always, the completed code can be found at: https://github.com/sahansera/go-grpc/tree/main/client
Creating client-side Stubs and Go modules
We will be using the same Protobuf files that we generated in our previous step. If you haven’t seen that already head over to my previous post.
We will create a new folder called client at the root of the project and initialize it with a Go module.
mkdir client && cd client
go mod init bookshop/clientFrom the repository root, generate the Protobuf message types and gRPC client interface into the client module:
protoc --proto_path=proto proto/*.proto --go_out=client --go-grpc_out=clientThis produces bookshop.pb.go for the messages and bookshop_grpc.pb.go for the generated client and server interfaces. Both are generated artifacts, so change the .proto file and rerun the command rather than editing these files by hand.

Implementing the gRPC client
Now that we have the modules we can go and implement the code for the client.
To call the server, create a gRPC ClientConn with grpc.NewClient. Despite the type name, it represents a reusable virtual channel that manages name resolution and underlying connections for generated clients.
💡 This local sample uses
insecure.NewCredentials(). Configure TLS and authentication before connecting across an untrusted network.
The rough skeleton of the client code looks like the following.
// ...
func main() {
conn, err := grpc.NewClient(
"localhost:8080",
grpc.WithTransportCredentials(insecure.NewCredentials()),
)
if err != nil {
log.Fatalf("failed to create client: %v", err)
}
defer conn.Close()
client := pb.NewInventoryClient(conn)
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
bookList, err := client.GetBookList(ctx, &pb.GetBookListRequest{})
if err != nil {
log.Fatalf("failed to get book list: %v", err)
}
log.Printf("book list: %v", bookList)
}The explanation of this code is as follows:
grpc.NewClientcreates the reusable gRPC channel forlocalhost:8080. It does not perform network I/O immediately; the first RPC causes the channel to connect.pb.NewInventoryClientwraps that channel with the strongly typed interface generated frombookshop.proto.context.WithTimeoutbounds the call to five seconds. gRPC does not set a deadline by default, so usingcontext.Background()directly could leave the caller waiting indefinitely during a dependency failure.GetBookListsends the generated request type and returns either the generated response or a gRPC status error.
Communicating with the server
From the repository root, start the server. It listens on port 8080:
make serverIn another terminal, run the client:
make clientThe terminal will print the two books returned by the server.

Nice! As you can see, the generated client makes the happy path small 🎉 The production work sits around that call: TLS and identity, realistic deadlines, status-aware retry policy, observability, and deciding which RPCs are safe to retry. A deadline limits waiting; it does not make a non-idempotent operation safe to repeat 😊
Conclusion
In this article, we reused the server’s Protocol Buffers contract to generate a Go client, created one reusable channel, and bounded the RPC with a deadline. That combination gives the caller a typed API without letting a failed dependency hold it forever.
I hope this article cleared up a lot of confusion that you had about gRPC. Please feel free to share your questions, thoughts, or feedback in the comments section below. Until next time 👋