# gRPC Quickstart using Golang

## What is gRPC?

gRPC is a modern open source high performance RPC framework that can run in any environment. It can efficiently connect services in and across data centers with pluggable support for load balancing, tracing, health checking and authentication. It is also applicable in last mile of distributed computing to connect devices, mobile applications and browsers to backend services.

source: [grpc.io](https://grpc.io/)

## Prerequisites

* protoc - [https://grpc.io/docs/protoc-installation/](https://grpc.io/docs/protoc-installation/)
    
* Golang plugins for protocol compilers
    

```bash
go install google.golang.org/protobuf/cmd/protoc-gen-go@v1.28
go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@v1.2
```

Make sure the `GOPATH/bin` is part of your PATH env

```bash
export PATH="$PATH:$(go env GOPATH)/bin"
```

Now, we are ready to get started.

## Steps

* Setup Projects
    
* Create gRPC server
    
    * Generate proto spec file
        
* Create gRPC client
    
* Test RPCs
    

### Setup Projects

To keep things simple, lets create two projects

* Server
    
* Client
    

Add simple `main.go` files in each and initialize go module (ex - `go mod init github.com/mridulganga/server`), also make sure to add them in GOPATH as client would need to import a file exposed by the server.

### Create gRPC server

#### Generate proto spec file

Create a new file called helloworld.proto in server project's `pkg/helloworld` folder

```bash
syntax = "proto3";

option go_package = "github.com/mridulganga/server/pkg/helloworld";
package helloworld;

service Greeter {
  rpc SayHello (HelloRequest) returns (HelloReply) {}
}

message HelloRequest {
  string name = 1;
}

message HelloReply {
  string message = 1;
}
```

Now cd to the folder and run the following command to generate the protobuf and gRPC interface

```bash
cd server/pkg/helloworld
protoc --go_out=. --go_opt=paths=source_relative \
    --go-grpc_out=. --go-grpc_opt=paths=source_relative \
    helloworld.proto
```

The above step should generate two files in the same folder

* helloworld.pb.go
    
* helloworld\_grpc.pb.go
    

Create the server in main.go (`server/main.go`)

```bash
package main

import (
	"context"
	"flag"
	"fmt"
	"log"
	"net"

	"google.golang.org/grpc"
	pb "github.com/mridulganga/server/pkg/helloworld"
)

var (
	port = flag.Int("port", 50051, "The server port")
)

// server is used to implement helloworld.GreeterServer.
type server struct {
	pb.UnimplementedGreeterServer
}

// SayHello implements helloworld.GreeterServer
func (s *server) SayHello(ctx context.Context, in *pb.HelloRequest) (*pb.HelloReply, error) {
	log.Printf("Received: %v", in.GetName())
	return &pb.HelloReply{Message: "Hello " + in.GetName()}, nil
}

func main() {
	flag.Parse()
	lis, err := net.Listen("tcp", fmt.Sprintf(":%d", *port))
	if err != nil {
		log.Fatalf("failed to listen: %v", err)
	}
	s := grpc.NewServer()
	pb.RegisterGreeterServer(s, &server{})
	log.Printf("server listening at %v", lis.Addr())
	if err := s.Serve(lis); err != nil {
		log.Fatalf("failed to serve: %v", err)
	}
}
```

Code taken from [https://github.com/grpc/grpc-go/blob/master/examples/helloworld/greeter\_server/main.go](https://github.com/grpc/grpc-go/blob/master/examples/helloworld/greeter_server/main.go)

### Create gRPC client

Create the client in main.go (`client/main.go`)

```bash
package main

import (
	"context"
	"flag"
	"log"
	"time"

	"google.golang.org/grpc"
	"google.golang.org/grpc/credentials/insecure"
	pb "github.com/mridulganga/server/pkg/helloworld"
)

const (
	defaultName = "world"
)

var (
	addr = flag.String("addr", "localhost:50051", "the address to connect to")
	name = flag.String("name", defaultName, "Name to greet")
)

func main() {
	flag.Parse()
	// Set up a connection to the server.
	conn, err := grpc.Dial(*addr, grpc.WithTransportCredentials(insecure.NewCredentials()))
	if err != nil {
		log.Fatalf("did not connect: %v", err)
	}
	defer conn.Close()
	c := pb.NewGreeterClient(conn)

	// Contact the server and print out its response.
	ctx, cancel := context.WithTimeout(context.Background(), time.Second)
	defer cancel()
	r, err := c.SayHello(ctx, &pb.HelloRequest{Name: *name})
	if err != nil {
		log.Fatalf("could not greet: %v", err)
	}
	log.Printf("Greeting: %s", r.GetMessage())
}
```

code taken from [https://github.com/grpc/grpc-go/blob/master/examples/helloworld/greeter\_client/main.go](https://github.com/grpc/grpc-go/blob/master/examples/helloworld/greeter_client/main.go)

### Test RPC

Run the server

```bash
go run server/main.go &
```

Note that we are using & to run server in background, alternatively you can open a new terminal for running the client

Run the client

```bash
go run client/main.go
go run client/main.go -name mridul
```

The client should log "Greeting world" or the name which is supplied. The client is using gRPC to connect to the server and call SayHello method on the server.
