MySql tutorial : Building RESTful APIs with the Gin framework
Repository
https://github.com/gin-gonic/gin
What Will I Learn?
- Creating a REST API with the go-restful package
- Creating a connection to MySql database
- Introducing the Gin framework for creating a REST API
- Testing the RESTful API with this GUI tool
Requirements
State the requirements the user needs in order to follow this tutorial.
- Localhost xampp
- Basic GoLang
- Basic Gin Golang
- Basic Database MySQL
Difficulty
Intermediate
Tutorial Contents
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:
- GET
- POST
- PUT
- PATCH
- DELETE
Breakdown code
package main
import (
"bytes"
"database/sql"
"fmt"
"net/http"
"github.com/gin-gonic/gin"
_ "github.com/go-sql-driver/mysql"
)
- Package bytes implements functions for the manipulation of byte slices. It is analogous to the facilities of the strings package.
- Package sql provides a generic interface around SQL (or SQL-like) databases.
- Package fmt implements formatted I/O with functions
- Imported a few packages. github.com/gin-gonic/gin, github.com/go-sql-driver/mysql is the data service we created before.
- net/http is the core package we used to handle an HTTP request through its HandleFunc function. That function's arguments are http.Request and http.ResponseWriter. Those two deal with the request and response of an HTTP request.
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")
}
- In every gin app, we should create a Default or New gin router
- We can specify :port on which our Gin applications run using port 3000
- We will keep the article structure simple with just three fields - Id, First_Name and Last_Name. This can be represented with a struct as follows:
- The Data Source Name has a common format, but without type-prefix (optional parts marked by squared brackets):
- example : [username[:password]@][protocol[(address)]]/dbname[?param1=value1&...¶mN=valueN]
// 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)
})
- Routing is one of the core features that all modern frameworks provide. Any web page or an API end point is accessed by a URL. Frameworks use routes to handle requests to these URLs.
- Gin offers a fast router that's easy to configure and use. Apart from handling specified URLs, Gin routers can also handle patterns and grouped URLs.
- A GET method fetches the given resource from the server. To specify a resource, GET uses a few types of URI queries:
- Query parameters
- Path-based parameters
- We use http.StatusOK to set the status code of the response header. The WriteHeader and Write functions are available on the response object for writing the header and body, respectively.
/// 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),
})
})
- In this part, create and initialize a new Buffer using string as its initial contents. It is intended to prepare a buffer to read an existing string.
- The PUT method is similar to POST. It is used to replace the resource that already exists. The main difference is that PUT is idempotent. A POST call creates two instances with the same data. But PUT updates a single resource that already exists.
// 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:
Comment deleted
Need help? Write a ticket on https://support.utopian.io/.
Chat with us on Discord.
[utopian-moderator]
Thank you for your moderation, I've updated my tittle too.
Your contribution has been found to be a copy of https://blog.narenarya.in/build-rest-api-go-mysql.html
This is considered plagiarism. Plagiarism is a serious offense, and hence your account has been banned for 30 days from receiving Utopian reviews.
Future plagiarism can lead to permanent ban of your account
Need help? Write a ticket on https://support.utopian.io/.
Chat with us on Discord.
[utopian-moderator]
I upvoted your post.
Cheers to you.
@Pinoy
Posted using https://Steeming.com condenser site.
Hi @elingmeyatmaja!
Your post was upvoted by @steem-ua, new Steem dApp, using UserAuthority for algorithmic post curation!
Your post is eligible for our upvote, thanks to our collaboration with @utopian-io!
Feel free to join our @steem-ua Discord server
Congratulations @elingmeyatmaja! You have completed the following achievement on the Steem blockchain and have been rewarded with new badge(s) :
You got your First payout
Click on the badge to view your Board of Honor.
If you no longer want to receive notifications, reply to this comment with the word
STOP
Do not miss the last post from @steemitboard:
Congratulations @elingmeyatmaja! You received a personal award!
Click here to view your Board
Do not miss the last post from @steemitboard:
Congratulations @elingmeyatmaja! You received a personal award!
You can view your badges on your Steem Board and compare to others on the Steem Ranking
Vote for @Steemitboard as a witness to get one more award and increased upvotes!