Enter to gRPC in Go first server
Tags: go, tutorial, grpc, beginners
Published: 2020-02-06 23:44:17

## Introduction

Hey, friends! 😉 I postponed this article series for a long time, because I was not sure how I felt about **gRPC**. But now, I've done one micro-service using this technology and... 

I'm **ready** to talk about it! 😅

### Table of contents

1. [Get started](#ch-1)
  - [Protocol Buffers](#ch-1-1)
  - [Packages for use gRPC in Golang](#ch-1-2)
  - [gRPC client](#ch-1-3)
2. [Repository with full code example](#ch-2)
3. [Project structure](#ch-3)
4. [Create proto file](#ch-4)
  - [Generate Go code from proto file](#ch-4-1)
5. [Create gRPC server](#ch-5)
6. [The Call from gRPC client](#ch-6)
  - [Evans live demo](#ch-6-1)

<a name="ch-1"></a>
## Get started

[gRPC](https://grpc.io) is an open source high performance RPC _framework_, who can run in any environments and written on many programming languages.

> ☝️ **Good to know:** Remote Procedure Call (RPC, for a short) is a powerful technique for constructing distributed, client-server based applications.

#### Main features 

- Start quickly and scale
- Simple service definition
- Works across languages and platforms
- Bi-directional streaming and integrated auth

#### How it works?

Please, see diagram below for a better understanding of _how gRPC works_:

![grpc schema](https://grpc.io/img/landing-2.svg)

That is, if you have written a service on **C++** or **Go**, but your colleagues write in **Java** or **Ruby** — it's not a problem at all. Give them your `.proto` file and they will generate their own code for the client part! 🍿

> ⚠️ I'm **not** aiming at a total parse of _all nuances of gRPC_ and its ecosystem. I leave that to you as **homework** assignment.

<a name="ch-1-1"></a>
### Protocol Buffers

Follow official Google [Developer Guide](https://developers.google.com/protocol-buffers/docs/overview) for `protobuf`:

> Protocol buffers are a flexible, efficient, automated mechanism for serializing structured data [...] You define how you want your data to be structured once, then you can use special generated source code to easily write and read your structured data [...] You can even update your data structure without breaking deployed programs [...]

But what does it really mean? It's easier than it looks! 😏

1. With Protocol Buffers you can easily describe structures;
2. Built-in code generator will do the basic work for you;
3. No problem to switch to another programming language;

#### How to install? 

Go to Protocol Buffers [download page](https://developers.google.com/protocol-buffers/docs/downloads) and install latest version for your system (supported Windows, GNU/Linux and macOS). 

>✨ **Tip**: macOS users can install Protocol Buffers from Homebrew.
>
> `$ brew install protobuf`

<a name="ch-1-2"></a>
### Packages for use gRPC in Golang

- First, install the `go-grps` package:

```console
$ go get -u google.golang.org/grpc
```

- Second, install the `protoc` plugin (for Protocol Buffers v3):

```console
$ go get -u github.com/golang/protobuf/protoc-gen-go
```

> That's all you need to get started! Now, you're ready to generate Go code from your `.proto` files.

<a name="ch-1-3"></a>
### gRPC client

The development of the gRPC client is **beyond** the scope of this article, so let's use turnkey solution — [Evans](https://github.com/ktr0731/evans) — universal gRPC client.

- Install Evans:

```console
$ go get -u github.com/ktr0731/evans
```

<a name="ch-2"></a>
## 🕓 No time to read more?

I created repository with full code example on my GitHub especially for you 👌

{% github koddr/example-go-grpc-server no-readme %}

Just `git clone` and read instructions from `README`.

![project structure](https://dev-to-uploads.s3.amazonaws.com/i/0a1079u44u2xhbauwntt.jpg)

<a name="ch-3"></a>
## Project structure

```console
$ tree .
.
├── Makefile
├── go.mod
├── go.sum
├── api
│   └── proto
│       └── adder.proto     <-- proto file
├── cmd
│   └── server
│       └── main.go         <-- main app
└── pkg
    ├── adder
    │   └── grpcserver.go   <-- methods for gRPC server
    └── api
        └── adder.pb.go     <-- auto generated code from .proto file
```

<a name="ch-4"></a>
## Create proto file

```proto
// ./api/proto/adder.proto

syntax = "proto3"; // use proto file v3

package api; // name of package

// Define service Adder
service Adder {
    rpc Add (AddRequest) returns (AddResponse) {}
}

// Define service methods

message AddRequest {
    int32 x = 1; // Unique ID number for X
    int32 y = 2; // Unique ID number for Y
}

message AddResponse {
    int32 result = 1; // Unique ID number for result
}
```

<a name="ch-4-1"></a>
### Generate Go code from `.proto` file

```console
$ protoc -I api/proto --go_out=plugins=grpc:pkg/api api/proto/adder.proto
```

It generated `adder.pb.go` file with complete Go code on folder `./pkg/api` 👍

<a name="ch-5"></a>
## Create gRPC server

- Main app: 

```go
// ./cmd/server/main.go

package main

import (
	"log"
	"net"

	"github.com/koddr/example-go-grpc-server/pkg/adder"
	"github.com/koddr/example-go-grpc-server/pkg/api"
	"google.golang.org/grpc"
)

func main() {
	// Create new gRPC server instance
	s := grpc.NewServer()
	srv := &adder.GRPCServer{}

	// Register gRPC server
	api.RegisterAdderServer(s, srv)

	// Listen on port 8080
	l, err := net.Listen("tcp", ":8080")
	if err != nil {
		log.Fatal(err)
	}

	// Start gRPC server
	if err := s.Serve(l); err != nil {
		log.Fatal(err)
	}
}
```

- Methods for gRPC server:

```go
// ./pkg/adder/grpcserver.go

package adder

import (
	"context"

	"github.com/koddr/example-go-grpc-server/pkg/api"
)

// GRPCServer struct
type GRPCServer struct{}

// Add method for calculate X + Y
func (s *GRPCServer) Add(ctx context.Context, req *api.AddRequest) (*api.AddResponse, error) {
	return &api.AddResponse{
		Result: req.GetX() + req.GetY(),
	}, nil
}

```

<a name="ch-6"></a>
## The Call from gRPC client 📲

We're ready to make our first gRPC call:

- Run _gRPC server_ by command (from root of project folder):

```console
$ go run ./cmd/server/...
```

- Go to _another_ console session and connect to server with Evans:

```console
$ evans api/proto/adder.proto -p 8080
```

- Into Evans, call to `Add()` method and type `x` and `y`:

```bash
api.Adder@127.0.0.1:8080> call Add

x (TYPE_INT32) => 10
y (TYPE_INT32) => 5

{
  "result": 15
}
```

>✨ **Tip**: Evans support full auto-complete. Just use arrows and hit `Tab` for apply suggestion.

<a name="ch-6-1"></a>
### 📺 Evans live demo

[![asciicast](https://asciinema.org/a/298722.svg)](https://asciinema.org/a/298722)

## Photo by

[Title] Lorenzo Herrera https://unsplash.com/photos/p0j-mE6mGo4
[1] Kaleidico https://unsplash.com/photos/26MJGnCM0Wc

<a name=""></a>
## P.S.

If you want more articles (like this) on this blog, then post a comment below and subscribe to me. Thanks! 😻

And of course, you can help me make developers' lives even better! Just connect to one of my projects as a contributor. It's easy!

My projects that need your help (and stars) 👇

- 🔥 [gowebly][gowebly_url]: A next-generation CLI tool for easily build amazing web applications with Go on the backend, using htmx & hyperscript and the most popular atomic/utility-first CSS frameworks on the frontend.
- ✨ [create-go-app][cgapp_url]: Create a new production-ready project with Go backend, frontend and deploy automation by running one CLI command.
- 🏃 [yatr][yatr_url]: Yet Another Task Runner allows you to organize and automate your routine operations that you normally do in Makefile (or else) for each project.
- 📚 [gosl][gosl_url]: The Go Snippet Library provides snippets collection for working with routine operations in your Go programs with a super user-friendly API and the most efficient performance.
- 🏄‍♂️ [csv2api][csv2api_url]: The parser reads the CSV file with the raw data, filters the records, identifies fields to be changed, and sends a request to update the data to the specified endpoint of your REST API.
- 🚴 [json2csv][json2csv_url]: The parser can read given folder with JSON files, filtering and qualifying input data with intent & stop words dictionaries and save results to CSV files by given chunk size.

<!-- Footer links -->

[gowebly_url]: https://github.com/gowebly
[cgapp_url]: https://github.com/create-go-app
[yatr_url]: https://github.com/koddr/yatr
[gosl_url]: https://github.com/koddr/gosl
[csv2api_url]: https://github.com/koddr/csv2api
[json2csv_url]: https://github.com/koddr/json2csv