Building a Basic gRPC Server and Client in Go
Building a Basic gRPC Server and Client in Go
In the ever-evolving world of microservices and distributed systems, gRPC provides a high-performance framework to build APIs. Its efficient binary serialization, and comprehensive support for numerous languages including Go, make it an excellent choice for communication between services. This article guides you through building a basic gRPC server and client in Go with complete code samples.
Prerequisites
To follow along, ensure you have the following:
- Go installed (version
1.16
or later) - Protocol Buffer Compiler installed
- Basic knowledge of Go programming language
- Basic knowledge of gRPC
Table of Contents
- Introduction to gRPC and Protocol Buffers
- Building a Basic gRPC Server in Go
- Building a gRPC Client in Go
- Running and Testing the Application
- Conclusion
Introduction to gRPC and Protocol Buffers
gRPC is a high-performance, open-source framework developed by Google. It uses Protocol Buffers (protobuf) as its interface definition language, defining services and message types for communication.
First, we need to define our service using protobuf. Install the protobuf compiler and Go protobuf plugin:
go install google.golang.org/protobuf/cmd/protoc-gen-go@v1.26
go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@v1.1
Code Structure
learninggrpc/
├── go.mod
├── pb/
│ ├── hello.pb.go
│ └── hello_grpc.pb.go
├── client/
│ └── main.go
└── server/
└── main.go
go mod init learninggrpc
Now, let’s create a proto
file called hello.proto
in the pb
directory to define a simple Hello
service:
syntax = "proto3";
option go_package = "learninggrpc/pb";
service HelloService {
rpc SayHello (HelloRequest) returns (HelloResponse);
}
message HelloRequest {
string greeting = 1;
}
message HelloResponse {
string reply = 1;
}
Building a Basic gRPC Server in Go
Once we have our service definition, we can proceed to build our gRPC server. First, we need to generate Go code from our proto
file:
protoc --go_out=. --go_opt=paths=source_relative --go-grpc_out=. --go-grpc_opt=paths=source_relative hello.proto
Now, let’s build our gRPC server:
package main
import (
"context"
"log"
"net"
"learninggrpc/pb"
"google.golang.org/grpc"
)
type server struct {
pb.UnimplementedHelloServiceServer
}
func (s *server) SayHello(ctx context.Context, in *pb.HelloRequest) (*pb.HelloResponse, error) {
return &pb.HelloResponse{Reply: "Hello " + in.GetGreeting()}, nil
}
func main() {
lis, err := net.Listen("tcp", ":50051")
if err != nil {
log.Fatalf("failed to listen: %v", err)
}
s := grpc.NewServer()
pb.RegisterHelloServiceServer(s, &server{})
if err := s.Serve(lis); err != nil {
log.Fatalf("failed to serve: %v", err)
}
}
Building a gRPC Client in Go
Now that we have our server, let’s create a gRPC client to communicate with it:
package main
import (
"context"
"log"
"time"
"learninggrpc/pb"
"google.golang.org/grpc"
)
func main() {
conn, err := grpc.Dial("localhost:50051", grpc.WithInsecure(), grpc.WithBlock())
if err != nil {
log.Fatalf("did not connect: %v", err)
}
defer conn.Close()
c := pb.NewHelloServiceClient(conn)
ctx, cancel := context.WithTimeout(context.Background(), time.Second)
defer cancel()
r, err := c.SayHello(ctx, &pb.HelloRequest{Greeting: "world"})
if err != nil {
log.Fatalf("could not greet: %v", err)
}
log.Printf("Greeting: %s", r.GetReply())
}
Running and Testing the Application
Finally, start the server, and then run the client:
go run server.go
go run client.go
The client should print: "Greeting: Hello world"
.
Conclusion
In this tutorial, we’ve walked through the steps of creating a basic gRPC server and client in Go. With gRPC, you can build efficient, high-performance microservices that are language-agnostic. If you’re interested in delving deeper into gRPC’s operational mechanics, data types, and how it powers efficient remote procedure calls, our comprehensive guide, Introduction to gRPC, is an excellent resource.
Subscribe to Faizan Bashir
Get the latest posts delivered right to your inbox