https://github.com/gin-gonic/gin
State the requirements the user needs in order to follow this tutorial.
Intermediate
In this chapter, we are going to use a framework for simplifying building REST services. First, we will take a quick look at gin. Gin-gonic is a framework based on the httprouter. In this section I will show you how build REST service gin connect to mysql.
Prepare your databases
To install Gin package, you need to install Go and set your Go workspace first. GOPATH is nothing but the current appointed workspace on your machine. It is an
environment variable that tells the Go compiler about where your source code, binaries,
and packages are placed. While developing, set the GOPATH to one
of your projects. The Go compiler now activates that project.
Download and install it:
$ go get -u github.com/gin-gonic/gin
Simple install the package to your $GOPATH with the go tool from shell:
$ go get -u github.com/go-sql-driver/mysql
Make sure Git is installed on your machine and in your system's PATH.
REST uses the URI to decode its resource to be handled. There are quite a few REST verbs available, but six of them are used frequently. They are as follows:
Breakdown code
package main
import (
"bytes"
"database/sql"
"fmt"
"net/http"
"github.com/gin-gonic/gin"
_ "github.com/go-sql-driver/mysql"
)
package main
import (
"bytes"
"database/sql"
"fmt"
"net/http"
"github.com/gin-gonic/gin"
_ "github.com/go-sql-driver/mysql"
)
func main() {
db, err := sql.Open("mysql", "root:passapp@tcp(127.0.0.1:3306)/gotest")
if err != nil {
fmt.Print(err.Error())
}
defer db.Close()
// make sure connection is available
err = db.Ping()
if err != nil {
fmt.Print(err.Error())
}
type Person struct {
Id int
First_Name string
Last_Name string
}
router := gin.Default()
// Add API handlers here
router.Run(":3000")
}
// GET a person detail
router.GET("/person/:id", func(c *gin.Context) {
var (
person Person
result gin.H
)
id := c.Param("id")
row := db.QueryRow("select id, first_name, last_name from person where id = ?;", id)
err = row.Scan(&person.Id, &person.First_Name, &person.Last_Name)
if err != nil {
// If no results send null
result = gin.H{
"result": nil,
"count": 0,
}
} else {
result = gin.H{
"result": person,
"count": 1,
}
}
c.JSON(http.StatusOK, result)
})
/// GET all persons
router.GET("/persons", func(c *gin.Context) {
var (
person Person
persons []Person
)
rows, err := db.Query("select id, first_name, last_name from person;")
if err != nil {
fmt.Print(err.Error())
}
for rows.Next() {
err = rows.Scan(&person.Id, &person.First_Name, &person.Last_Name)
persons = append(persons, person)
if err != nil {
fmt.Print(err.Error())
}
}
defer rows.Close()
c.JSON(http.StatusOK, gin.H{
"result": persons,
"count": len(persons),
})
})
Here, the resource query is with the path parameter. Query parameters are intended to add detailed information to identify a resource from the server. For example, take this sample fictitious API. Let us assume this API is created for fetching, creating, and updating
// POST new person details
router.POST("/person", func(c *gin.Context) {
var buffer bytes.Buffer
first_name := c.PostForm("first_name")
last_name := c.PostForm("last_name")
stmt, err := db.Prepare("insert into person (first_name, last_name) values(?,?);")
if err != nil {
fmt.Print(err.Error())
}
_, err = stmt.Exec(first_name, last_name)
if err != nil {
fmt.Print(err.Error())
}
// Fastest way to append strings
buffer.WriteString(first_name)
buffer.WriteString(" ")
buffer.WriteString(last_name)
defer stmt.Close()
name := buffer.String()
c.JSON(http.StatusOK, gin.H{
"message": fmt.Sprintf(" %s successfully created", name),
})
})
The POST method is used to create a resource on the server. A successful POST operation returns a 201 status code.
// PUT - update a person details
router.PUT("/person", func(c *gin.Context) {
var buffer bytes.Buffer
id := c.Query("id")
first_name := c.PostForm("first_name")
last_name := c.PostForm("last_name")
stmt, err := db.Prepare("update person set first_name= ?, last_name= ? where id= ?;")
if err != nil {
fmt.Print(err.Error())
}
_, err = stmt.Exec(first_name, last_name, id)
if err != nil {
fmt.Print(err.Error())
}
// Fastest way to append strings
buffer.WriteString(first_name)
buffer.WriteString(" ")
buffer.WriteString(last_name)
defer stmt.Close()
name := buffer.String()
c.JSON(http.StatusOK, gin.H{
"message": fmt.Sprintf("Successfully updated to %s", name),
})
})
// Delete resources
router.DELETE("/person", func(c *gin.Context) {
id := c.Query("id")
stmt, err := db.Prepare("delete from person where id= ?;")
if err != nil {
fmt.Print(err.Error())
}
_, err = stmt.Exec(id)
if err != nil {
fmt.Print(err.Error())
}
c.JSON(http.StatusOK, gin.H{
"message": fmt.Sprintf("Successfully deleted user: %s", id),
})
})
The DELETE API method is used to delete a resource from the database. It is similar to PUT but without any body. It just needs an ID of the resource to be deleted. Once a resource gets deleted, subsequent GET requests return a 404 not found status.
If we run this program:
run main.go
The following screenshot shows the JSON response body in Postman for the HTTP GET
request: