DEV Community

loading...
Cover image for How to implement a simple gRPC service using Golang

How to implement a simple gRPC service using Golang

penthaapatel
Recent CS Graduate Seeking Entry-Level Programming Position
・3 min read

How to implement a simple RPC service using Golang

If you want a general introduction to RPC you might want to check out my previous article in this series - A concise guide to gRPC for beginners

The implemented code can be found on my GitHub Repository :
Link to GitHub repository

Before you begin

Workflow

  • Define protocol - Write .proto file
  • Compile it - generate necessary protobuf related files and client and server stubs
  • Write Client code
  • Write Server code
  • Run the server and client code, check if it works

A simple RPC service that can create blog posts

Overview

  • Client sends a request to the server to create a blog post with a given title and contents.
  • The server saves the newly created blog posts in an in-memory storage.
  • Since this particular article focuses on implementing RPC services, we use an in-memory storage to save out blog posts. This in-memory storage can be replaced with any database at the backend later.
  • The database can be integrated later by utilising the power of interfaces in Golang. ### Directory structure
grpcblog
├── Makefile
├── blog
│   ├── blog.pb.go
│   ├── blog.proto
│   └── blog_grpc.pb.go
├── client
│   └── client.go
├── server
│   └── server.go
├── storage
    └── storage.go
Enter fullscreen mode Exit fullscreen mode

.proto file

  • message Blog defines the structure of the blog post and contains 2 fields - title and body.
message Blog{
   string title = 1;
   string body =2;
 }
Enter fullscreen mode Exit fullscreen mode
  • message BlogRequest defines the structure of the client request - has 1 field - Blog.
message BlogRequest {
   Blog blog = 1;
 }
Enter fullscreen mode Exit fullscreen mode
  • message BlogResponse defines the structure of the server response - contains 2 fields -
    • id : a universally unique identifier (UUID) generated on successful creation of a new post.
    • created : a boolean value set to true if CreatePost is successful; false otherwise.
 message BlogResponse{
   string id = 1;
   bool created = 2;
 }
Enter fullscreen mode Exit fullscreen mode
  • The proto file contains a simple RPC service CreatePost - client sends a single request to the server and the server responds back with a single response. The RPC service CreatePost sends a BlogRequest from the client and the server responds with a BlogResponse.
  service BlogService{
   rpc CreatePost(BlogRequest) returns (BlogResponse) {}
 }
Enter fullscreen mode Exit fullscreen mode

Compiling the .proto files

Use the following command to compile the .protofiles:

protoc --go_out=. --go_opt=paths=source_relative --go-grpc_out=. --go-grpc_opt=paths=source_relative blog/blog.proto
Enter fullscreen mode Exit fullscreen mode

This will generate two files:

blog/blog_grpc.pb.go
Enter fullscreen mode Exit fullscreen mode

blog_grpc.pb.go contains server and client stubs. The interfaces BlogServiceClient and BlogServiceServer are not implemented. These interfaces will be later implemented in our server and client code. We will have to write own own implementation of server and client.

blog/blog.pb.go
Enter fullscreen mode Exit fullscreen mode

blog.pb.go contains protocol buffer code - responsible for binary serialization of data when it is transported between server and client.

Define in-memory storage

  • storage.go contains custom functions to implement the temporary in-memory storage.
  • Contains an interface BlogStorage interface with a Save() and a View() function.
type BlogStorage interface {
    Save(blog *blog.Blog, id string) error
    View()
}

type InMemoryBlogStorage struct {
    mutex sync.RWMutex
    blogs map[string]*blog.Blog
}
Enter fullscreen mode Exit fullscreen mode
  • Blogs are saved in a map where key is the UUID and the value associated with it is the blog post.
  • To save the posts to a database, we can add another function like SaveToDB() that implements the BlogStorage interface.

Client code

  • Reads in the blog title from the console.
  • Reads in the blog contents from the console.
  • Contains the implementation of the function CreatePost that was unimplemented in BlogServiceClient interface in blog/blog_grpc.pb.go.

Server code

  • Creates and saves new blog posts to the in-memory storage by taking input data from the client.
  • Contains the implementation of the function CreatePost that was unimplemented in BlogServiceServer interface in blog/blog_grpc.pb.go.
  • Generates a universally unique identifier (UUID) when a new post is created and saved to the in-memory storage
  • Displays UUID of each new post upon successful creation of a new post

Final result

Run the server and client code in two separate terminals.
Run server

go run server/server.go
Enter fullscreen mode Exit fullscreen mode

Server running on terminal 1

Run client - Enter title and contents for the new blog post.

go run client/client.go
Enter fullscreen mode Exit fullscreen mode

Client running on terminal 2

And hurray! We have successfully created a new post using gRPC service.

Further reading - Some useful resources:

Discussion (0)