Here we will Gin framework for building our restful api. Gin is one of the best framework for GoLang. It also supports a lot of built in features like Authentication, Middleware, JSON Validation and Routing.
Here we will build restful api for our flutter app, which we built before. Previously we built the restful api using pure GoLang.
But this time we will use GoLang framework Gin. If you want to combine this CRUD operations with flutter app, go ahead check it out.
If you are just looking for a restful api using Go and Gin, then just follow along from here.
Project stucture
Our project stucture would look like below.
Go ahead create a folder name GG (you can name it anything you want).
Installation of Gin
First inside GG folder run the below command
go mod init gin.com/gin
With the above command, it will initialize GoLang for your project. Here gin.com/gin is just a name, you can name it anything.
To install Gin in your project, run the below command from your GG folder.
go get -u github.com/gin-gonic/gin
The above command will install Gin in your project directory. But before you do that,make sure you have Go install in your machine.
The above command will generate go.sum and go.mod in your project folder.
Database setup
First we are going to set up the database. Make sure in your machine Mysql is install and at the same time you have phpmyadmin or mysql work bench installed. Inside it create a database name task_management and then create a table name tasks.
Inside the GG folder create a folder name models and then create a file name db.go and put the below code
package models
import (
"github.com/jinzhu/gorm"
_ "github.com/jinzhu/gorm/dialects/mysql"
)
var DB *gorm.DB
func ConnectDatabase() {
database, err := gorm.Open("mysql", "root:123456@tcp(127.0.0.1:3306)/task_management")
if err != nil {
panic("Failed to connect to database!")
}
database.AutoMigrate(&Task{})
DB = database
}
Use your on password for gorm.Open() function. Here we create a database connection and make a reference for it so that we can call it later.
Later we will refer this database using DB.
The above code will also create a database table name using database.AutoMigrate(&Task{})
Task model
In the table we will have four fields,
id,
task_name,
task_detail
date
For these four fields we will create a model so that, we can interact with our table tasks.
And inside this models folder create a file name table.go
Code for model table table.go
package models
type Task struct {
ID uint `json:"id" gorm:"primary_key"`
TaskName string `json:"task_name"`
TaskDetail string `json:"task_detail"`
Date string `json:"date"`
}
Creating controller
Inside GG folder create another folder name controllers and inside this controllers folder create a file name task_controller.go
First put the below code inside this task_controller.go
package controllers
import (
"net/http"
"github.com/gin-gonic/gin"
"gin.com/gin/models"
)
type CreateTaskInput struct {
TaskName string `json:"task_name" binding:"required"`
TaskDetail string `json:"task_detail" binding:"required"`
}
type UpdateTaskInput struct{
TaskName string `json:"task_name" binding:"required"`
TaskDetail string `json:"task_detail" binding:"required"`
}
Here we imported necessary modules and then we created struct for creating and updating task.We will need them for JSON data validation.
Find All Tasks
To find all tasks put the funcion in the task_controller.go file
func FindTasks(c *gin.Context){
var tasks []models.Task
models.DB.Find(&tasks)
c.JSON(http.StatusOk, g.H{"data":tasks})
}
Create Task
func CreateTask(c *gin.Context) {
// Validate input
var input CreateTaskInput
if err := c.ShouldBindJSON(&input); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
// Create task
task := models.Task{TaskName: input.TaskName, TaskDetail: input.TaskDetail, Date: "2020-03-10 00:00:00"}
models.DB.Create(&task)
c.JSON(http.StatusOK, gin.H{"data": task})
}
Find a Task
func FindTask(c *gin.Context) { // Get model if exist
var task models.Task
id := c.Request.URL.Query().Get("id")
if err := models.DB.Where("id = ?", id).First(&task).Error; err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "Record not found!"})
return
}
c.JSON(http.StatusOK, gin.H{"data": task})
}
Update a Task
func UpdateTask(c *gin.Context) {
// Get model if exist
var task models.Task
id := c.Request.URL.Query().Get("id")
if err := models.DB.Where("id = ?", id).First(&task).Error; err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "Record not found!"})
return
}
// Validate input
var input UpdateTaskInput
if err := c.ShouldBindJSON(&input); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
models.DB.Model(&task).Updates(input)
c.JSON(http.StatusOK, gin.H{"data": task})
}
main.go
package main
import (
"github.com/gin-gonic/gin"
"gin.com/gin/models"
"gin.com/gin/controllers"
)
func main() {
r := gin.Default()
models.ConnectDatabase()
r.GET("/api/tasks", controllers.FindTasks)
r.POST("/api/tasks", controllers.CreateTask)
r.GET("/api/tasks/one", controllers.FindTask)
r.PUT("/api/tasks/update", controllers.UpdateTask)
r.Run()
}