DEV Community

Ayoub Ali
Ayoub Ali

Posted on

How to Build Simple REST-ful API with Go and Gin

Introduction

This tutorial introduces the basics of writing a RESTful web service API with Go and the Gin Web Framework (Gin).

You’ll get the most out of this tutorial if you have a basic familiarity with Go and its tooling.

Gin simplifies many coding tasks associated with building web applications, including web services. In this tutorial, you’ll use Gin to route requests, retrieve request details, and marshal JSON for responses.

In this tutorial, you will build a RESTful API server with different end-points

The tutorial includes the following sections:

Design API endpoints.

Create a folder for your code.
Create the data.
Write a handler to return all items.
Write a handler to add a new item.
Write a handler to return a specific item.

Project Structure

PROJECT STRUCTURE

STEP - 1

  • First we will create a main.go file in the root folder
  • Than we will run the go mod init basically we write the project name or any nae you want which is basically important it will create a go.mod file which will hold project name as module
go mod init json-server
Enter fullscreen mode Exit fullscreen mode
  • Because we are using gin web framework so we have to add in our project - run this command in terminal
 go get -u github.com/gin-gonic/gin
Enter fullscreen mode Exit fullscreen mode

Step - 2

Create a model for your API
In GO struct is simply a class

package model

type Game struct {
    ID       string  `json:"id"`
    NAME     string  `json:"name"`
    CATEGORY string  `json:"category"`
    PRICE    float32 `json:"price"`
}
Enter fullscreen mode Exit fullscreen mode

To see things visually we will give it some initial hard coded data to load

var InitialData = []Game{
    {
        ID:       "1",
        NAME:     "God of War",
        CATEGORY: "Open World",
        PRICE:    45.0,
    },
    {
        ID:       "2",
        NAME:     "World War",
        CATEGORY: "Fantasy",
        PRICE:    25.0,
    },
    {
        ID:       "3",
        NAME:     "BattleFiled",
        CATEGORY: "Shooter",
        PRICE:    15.0,
    },
}
Enter fullscreen mode Exit fullscreen mode

Step - 3

Create a folder inside root folder name helper or anything you like in this folder we will create the all the methods for our API

GET REQUEST

we are working on different folder so we don't basically need main package yet we will create our own package and import it into the main file.
Because of recent updates we can not directly use any other package we have to give reference schema for example

If we wanna get any function or method or anything we will use model.<name> just in this case we are using model.InitialData to get the hard-coded data

model "json-server/model"
Enter fullscreen mode Exit fullscreen mode
package helper

import (
    "net/http"

    model "json-server/model"

    "github.com/gin-gonic/gin"
)
// This will load all the data which is already available
func Get(c *gin.Context) {
    c.IndentedJSON(http.StatusOK, model.InitialData)
}

// getting data specific data based on ID
func GetByID(c *gin.Context) {
    // this getting the reference ID from JSON that we used
    id := c.Param("id")
    // for every data inside the our hard coded data
    for _, data := range model.InitialData {
        // if the ID match with our params ID we will return that specific data
        if data.ID == id {
            c.IndentedJSON(http.StatusOK, data)
            return
        }
    }
    // if not than We are Panic
    c.IndentedJSON(http.StatusNotFound, gin.H{"Panic": "Game Not Found"})
}
Enter fullscreen mode Exit fullscreen mode

Response in Our Browser

To see response and our data and if it's working correctly

  • Go to main.go file. Don't forget to write you functions name with capital word which means GLOBAL we can access it anywhere and w are dealing with external package like we call it package helper so we have to give it to the reference to access all the properties or anything
helper "json-server/helper"
Enter fullscreen mode Exit fullscreen mode
package main

import (
    helper "json-server/helper"

    "github.com/gin-gonic/gin"
)

func main() {
    // initializing our routers
    var router *gin.Engine = gin.Default()
    // to get everything
    router.GET("/games", helper.Get)
    // to get specific data
    router.GET("/games/:id", helper.GetByID)
    // setting local-host and 8000 as  port
    router.Run("localhost:8080")
}

Enter fullscreen mode Exit fullscreen mode
go run main.go
Enter fullscreen mode Exit fullscreen mode

After that our server will start running at localhost:8080
To see that data we have to do this

localhost:8080/games
Enter fullscreen mode Exit fullscreen mode
  • For Specific QUERY to access based on our ID
localhost:8080/games/1
// OR
localhost:8080/games/2
// OR
localhost:8080/games/3
Enter fullscreen mode Exit fullscreen mode

We are testing this inside Vscode so BUT you can use the same URL to see response in browser

GET REQUEST

POST REQUEST

package helper

import (
    model "json-server/model"
    "net/http"

    "github.com/gin-gonic/gin"
)

func Post(c *gin.Context) {
    // initializing our model structure to insert new data based on MODEL
    var newGames model.Game
    // BindJSON is use to bind newDATA inside our JSON demo data
    if err := c.BindJSON(&newGames); err != nil {
        // if there is error than Panic Situation
        println("Panic: Error")
        return
    }
    // if no error than we will append or add new data to our Initial dummy data
    model.InitialData = append(model.InitialData, newGames)
    // than we will see the response
    c.IndentedJSON(http.StatusCreated, newGames)
}
Enter fullscreen mode Exit fullscreen mode

Response

POST REQUEST

  • Data We added to GET and SEE all of them

GET POST REQUEST

DELETE REQUEST

package helper

import (
    "fmt"
    model "json-server/model"
    "net/http"

    "github.com/gin-gonic/gin"
)

func Delete(c *gin.Context) {
    // getting the reference oof the ID
    id := c.Param("id")
    // based on  index we will get every single data
    for i, singleGame := range model.InitialData {
        // if the ID in our json match with the our parameter ID
        if singleGame.ID == id {
            // we will delete the data
            model.InitialData = append(model.InitialData[:i], model.InitialData[i+1:]...)
            // to see the response
            c.IndentedJSON(http.StatusCreated, singleGame)
            // than we will print Means deleted successfully
            fmt.Println("Deleted Successfully")
        }
    }
}
Enter fullscreen mode Exit fullscreen mode

Response

On Right Side it shows which data we deleted based on the ID

DELETE REQUEST

UPDATE REQUEST

package helper

import (
    model "json-server/model"
    "net/http"

    "github.com/gin-gonic/gin"
)

func Update(c *gin.Context) {
    // we will query the data based on the ID
    id := c.Param("id")
    // and the data model to execute new data
    var updatedGame model.Game
    // based on our dummy data we will loop through each and every data
    for i, singleGame := range model.InitialData {
        // if the ID match with our reference ID
        if singleGame.ID == id {
            // we will update all these parameters
            singleGame.ID = updatedGame.ID
            singleGame.NAME = updatedGame.NAME
            singleGame.CATEGORY = updatedGame.CATEGORY
            singleGame.PRICE = updatedGame.PRICE
            // after that we will bind this new DATA to OLD data
            if err := c.BindJSON(&updatedGame); err != nil {
                // if there is an error we will panic
                println("Panic: Error Inserting NEW DATA")
                return
            }
            // than we will append all the data as JSON
            model.InitialData = append(model.InitialData[:i], updatedGame)
            // it will give us response
            c.IndentedJSON(http.StatusCreated, updatedGame)
        }
    }
}
Enter fullscreen mode Exit fullscreen mode

Response

Basically we are changing the first dummy data into new data we set ID to 4 and vice versa also other parameters

PATCH REQUEST

Main File after Implementing all the REQUEST

package main

import (
    helper "json-server/helper"

    "github.com/gin-gonic/gin"
)

func main() {
    var router *gin.Engine = gin.Default()
    router.Run("localhost:8080")
    router.GET("/games", helper.Get)
    router.GET("/games/:id", helper.GetByID)
    router.POST("/post", helper.Post)
    router.DELETE("/delete/:id", helper.Delete)
    router.PATCH("/update/:id", helper.Update)
}
Enter fullscreen mode Exit fullscreen mode

Final Thoughts:-

I know that is not perfect way to do everything but It's a simple and straight forward to do and Basically if we visit the official website GO DOCS for RestFUL API Using GIn the few of the stuff is outdated because many things has changed after the new Updates I hope this may help to those who are curious to explore different things in LIFE

Declaimer:-

Few of end-points I have changed

// To get all the DATA

localhost:8080/games

// To get Specific DATA

localhost:8080/games/<ID>

// To post REQUEST
localhost:8080/post

// To Delete based on specific ID

localhost:8080/delete/<ID>

// To PATCH -- UPDATE based on ID

localhost:8080/update/<ID>
Enter fullscreen mode Exit fullscreen mode

GITHUB LINK

Top comments (0)