Search⌘ K
AI Features

Solution 3: Working with gRPC

Explore how to implement gRPC services in Go by creating a RESTful server using the Gin framework that interacts with a gRPC server via protocol buffers. Understand setting up endpoints that call gRPC methods, establish connections with grpc.Dial, and handle JSON responses for data exchange.

We'll cover the following...

Solution

Here is a RESTful service that uses gRPC for data exchange. To execute the RESTful service:

  • Open a new terminal window and execute the rServer.go code using the following commands:

export GOROOT=/usr/local/go; export GOPATH=$HOME/go; export PATH=$GOPATH/bin:$GOROOT/bin:$PATH; cd usercode;
go run rServer.go
  • Then, open another terminal window and execute the following curl commands:

# curl http://localhost:8081/datetime
# curl http://localhost:8081/randompassword
# curl http://localhost:8081/randominteger
package main

import (
    "context"
    "github.com/gin-gonic/gin"
    "google.golang.org/grpc"
    "log"
    "net/http"
    "os"
    "github.com/Educative-Content/protoapi"
)

var grpcServerAddress = "localhost:8082" 

func main() {
    router := gin.Default()

    // Initialize a gRPC connection to the server
    conn, err := grpc.Dial(grpcServerAddress, grpc.WithInsecure())
    if err != nil {
        log.Fatalf("Failed to connect to gRPC server: %v", err)
    }
    defer conn.Close()

    client := protoapi.NewRandomClient(conn)

    // Define RESTful API endpoints
    router.GET("/datetime", func(c *gin.Context) {
        ctx := context.Background()
        response, err := client.GetDate(ctx, &protoapi.RequestDateTime{})
        if err != nil {
            c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
            return
        }
        c.JSON(http.StatusOK, gin.H{"datetime": response.Value})
    })

    router.GET("/randompassword", func(c *gin.Context) {
        ctx := context.Background()
        response, err := client.GetRandomPass(ctx, &protoapi.RequestPass{Seed: 100, Length: 8})
        if err != nil {
            c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
            return
        }
        c.JSON(http.StatusOK, gin.H{"password": response.Password})
    })

    router.GET("/randominteger", func(c *gin.Context) {
        ctx := context.Background()
        response, err := client.GetRandom(ctx, &protoapi.RandomParams{Seed: 100, Place: 1})
        if err != nil {
            c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
            return
        }
        c.JSON(http.StatusOK, gin.H{"integer": response.Value})
    })

    port := getPort()
    router.Run(":" + port)
}

func getPort() string {
    if len(os.Args) > 1 {
        return os.Args[1]
    }
    return "8081" // Default port
}
gServer.go and rServer,go

Code

...