Creating Basic Restful API in GO-lang

Ginanjar S.B
7 min readApr 13, 2022

--

Hello guys.
Finally, I’m back to writing some articles again. How are you guys? I wish you all always to be great.

Okay. Today, I want to share about how to create a Restful API in Go-lang. What is Restful API? It’s Application Programming Interface that conforms to the constraints of REST architectural style and allows for interaction with RESTful web services. So you can communicate to more than one application with API.

In this article I will share how to create it in Go-lang but just in the simple way and for basic concepts. So we will create it with data that is stored in a variable or slice. Next I’ll upgrade it to use a database.

Okay let’s do it.
First, create new project or new directory and I call it “go-api”. After that, we need to create file main.go for the main file. And then do command go mod init go-api to initialize go modules. okay, it’s done. Thank you. No, I’m joking :D

Oh wait, before we do more, I’ll mention you if in this article I’ll use gin-gonic as a framework to create Restful API. And we’ll create project about the Book Store in the small example. Ok, let continues.

After done to create file main.go and initialized go modules, we need to setup our structure directory like bellow. Oh ya, don’t worry about directory doc_images , that’s not important.

structure file.

Okay, based on the screenshot above, we’ll store our data in Model. So, let’s create a new directory that calls models and create new file in the directory with the name book.go. After that we’ll create struct for Book and create a slice to store data of the books like bellow.

package models

type Book struct {
ID int `json:"id"`
Title string `json:"title"`
Author string `json:"author"`
Qty int `json:"qty"`
}

var bookDatas = []Book{
{ID: 1, Title: "Akuntansi Pengantar 1", Author: "Supardi", Qty: 2},
{ID: 2, Title: "A-Z Psikologi : Berbagai kumpulan topik Psikologi", Author: "Zainul Anwar", Qty: 4},
{ID: 3, Title: "Kesehjateraan Sosial", Author: "Isbandi Rukminto Adi", Qty: 1},
}

After that we need to define some functions to communicate with our data in Book model. The functions are basic to create, read, update and delete data. So, you can create functions like bellow.

func GetAllBooks() []Book {
return bookDatas
}

func AddNewBook(newBook *Book) {
data := &bookDatas
newId := (*data)[len(*data)-1].ID + 1
newBook.ID = newId
bookDatas = append(bookDatas, *newBook)
}

The GetAllBooks() will use to get all data of the books in model and AddNewBook() will use to create new data to store in book model. After that, create some function like bellow to get book by ID and remove book by ID.

func GetBookById(id int) (*Book, error) {
for i, data := range bookDatas {
if data.ID == id {
return &bookDatas[i], nil
}
}

return nil, errors.New("Data not found")
}

func RemoveBookById(id int) (*Book, error) {
for i, data := range bookDatas {
if data.ID == id {
newData := &bookDatas

deletedData := (*newData)[i]

(*newData)[i] = (*newData)[len(*newData)-1]
*newData = (*newData)[:len(*newData)-1]

return &deletedData, nil
}
}

return nil, errors.New("Data cannot be deleted")
}

And than we need to create another function to update book by ID like bellow.

func UpdateBookById(id int, updateBook *Book) (*Book, error) {
for i, data := range bookDatas {
if data.ID == id {
newData := &bookDatas

oldData := (*newData)[i]
updateBook.ID = oldData.ID
(*newData)[i] = *updateBook

return &oldData, nil
}
}

return nil, errors.New("Data not found")
}

Nice. We have done to create book model.
After that, we need to define controllers to communicated and process our request from routes. So, create new file in directory controller with name book_controller.go and than create some function to handle request and sent response with JSON format.
In the file book_controller.go let’s define function to get all the books like code bellow.

package controllers

import (
"fmt"
"github.com/gin-gonic/gin"
"go-api/models"
"net/http"
"strconv"
)

func GetAllBooks(c *gin.Context) {
c.IndentedJSON(http.StatusOK, models.GetAllBooks())
}

The code c.IndentedJSON() will send response to client as JSON format with http status code 200and list data of the books. After that we’ll define some function to handle creating a new book, show the book by ID, delete the book by ID and update the book by ID. It’ll seem like code bellow.

func CreateBook(c *gin.Context) {
var newBook models.Book

if err := c.BindJSON(&newBook); err != nil {
c.IndentedJSON(http.StatusNotFound, gin.H{"msg": "Data can not created"})
return
}

models.AddNewBook(&newBook)
c.IndentedJSON(http.StatusCreated, newBook)
}

CreateBook() function will created new data of the book where the data will added by raw data from c.BindJSON() to variable newBook and then will be checked if there’s any error, it’ll send respond to client with message and close the function with return syntax. If there’s no error, data will append to dataBooks by method AddNewBook in our model.

Next, we need to define another function to show data by ID, delete data by ID and update data by ID. You can create that functions like bellow.

func ShowBook(c *gin.Context) {
id, err := strconv.Atoi(c.Param("id"))
if err != nil {
fmt.Println(err.Error())
}

book, err := models.GetBookById(id)
if err != nil {
c.IndentedJSON(http.StatusNotFound, gin.H{"msg": "Data Not Found"})
return
}

c.IndentedJSON(http.StatusOK, book)
}

func DeleteBook(c *gin.Context) {
id, err := strconv.Atoi(c.Param("id"))
if err != nil {
fmt.Println(err.Error())
}

book, err := models.RemoveBookById(id)
if err != nil {
c.IndentedJSON(http.StatusNotFound, gin.H{"msg": "Data Not Found"})
return
}

c.IndentedJSON(http.StatusOK, gin.H{"msg": "Data " + book.Title + " has been deleted"})
}

func UpdateBook(c *gin.Context) {
var updateBook models.Book

id, err := strconv.Atoi(c.Param("id"))
if err != nil {
fmt.Println(err.Error())
}

if err := c.BindJSON(&updateBook); err != nil {
c.IndentedJSON(http.StatusNotFound, gin.H{"msg": "Data can not created"})
return
}

book, errUpdate := models.UpdateBookById(id, &updateBook)
if errUpdate != nil {
c.IndentedJSON(http.StatusNotFound, gin.H{"msg": "Data Not Found"})
return
}

c.IndentedJSON(http.StatusOK, gin.H{"msg": "Data " + book.Title + " has been updated"})
}

The function ShowBook(), DeleteBook(), UpdateBook() will iterate all data to find the book by ID.
Okay, after that we need to create a router for define a URL to communicate with the model via controller by all functions in file book_controller.go. So, create a new file in directory routers and the name is books_router.go.
Define all route like bellow.

package routers

import (
"github.com/gin-gonic/gin"
"go-api/controllers"
)

func BookRouters(router *gin.Engine) {
router.GET("/books", controllers.GetAllBooks)
router.POST("/books", controllers.CreateBook)
router.GET("/book/:id", controllers.ShowBook)
router.DELETE("/book/delete/:id", controllers.DeleteBook)
router.PATCH("/book/update/:id", controllers.UpdateBook)
}

URL /books with method GET will call function GetAllBooks in our book_controller to show all data of the books.
/books with method POST will call function CreateBook in our controller to create a new book in our model. The :id is as parameter in our route to get data, update data and delete data by ID.

Okay, last but not least, let’s define our main function to run the service in file main.go and write code like bellow.

package main

import (
"fmt"
"github.com/gin-gonic/gin"
"go-api/routers"
)

func main() {
port := ":9000"
router := gin.Default()

routers.BookRouters(router)

router.Run(port)
fmt.Println("Server running on port" + port)
}

The variable port is used to define a port when the service is running. Variable router to initialize router from gin framework. After that we import our router and run the server with router.Run(port).

We have done with our setup and now let’s start the service with command go run main.go in our terminal.

go run main.g

After that open the Postman or another tools to access API and access with URL http://localhost:9000.
All URL you can access like bellow.

Get all books.
Add new book.
Show book by ID 1.
Update book by ID 2.
Delete book by ID 1.

Okay, we have created the basic or Restful API with GO-lang using gin framework. Next we’ll update this project with database to store data instead of variables in our model.

Thank you guys.
Keep learning and sharing.
See you soon.

Source code : Github.

--

--

Ginanjar S.B
Ginanjar S.B

Written by Ginanjar S.B

I am a web developer and flutter developer. Keep learning and sharing.

No responses yet