Create a pagination API with Go
Splitting larger content into distinct pages is known as pagination. This approach significantly enhances the user experience and speeds up the loading of web pages. This example will demonstrate how to create a pagination API using Gin Framework and use MySQL as a database.
Prerequisites
- Go 1.21
- MySQL
Setup project
Setting up the Go project dependencies.
go mod init app
go get github.com/gin-gonic/gin
go get gorm.io/gorm
go get gorm.io/driver/mysql
go get github.com/joho/godotenv
Create a testing database named "example" and run the database.sql file to import the table and data.
Project structure
├─ .env
├─ main.go
├─ config
│ └─ db.go
├─ controllers
│ └─ product_controller.go
├─ models
│ └─ product.go
├─ public
│ └─ index.html
└─ router
└─ router.go
Project files
.env
DB_HOST=localhost
DB_PORT=3306
DB_DATABASE=example
DB_USER=root
DB_PASSWORD=
db.go
This file sets up the database connection using GORM. It declares a global variable DB to hold the database connection instance to use later in our application.
package config
import (
"fmt"
"os"
"github.com/joho/godotenv"
"gorm.io/driver/mysql"
"gorm.io/gorm"
"gorm.io/gorm/schema"
)
var DB *gorm.DB
func SetupDatabase() {
godotenv.Load()
connection := fmt.Sprintf("%s:%s@tcp(%s:%s)/%s?charset=utf8mb4&parseTime=true", os.Getenv("DB_USER"), os.Getenv("DB_PASSWORD"), os.Getenv("DB_HOST"), os.Getenv("DB_PORT"), os.Getenv("DB_DATABASE"))
db, _ := gorm.Open(mysql.Open(connection), &gorm.Config{NamingStrategy: schema.NamingStrategy{SingularTable: true}})
DB = db
}
router.go
This file sets up routing for a Gin web application. It initializes a router for a pagination API and serves a static index.html file at the root URL.
package router
import (
"app/controllers"
"github.com/gin-gonic/gin"
)
func SetupRouter() {
productController := controllers.ProductController{}
router := gin.Default()
router.StaticFile("/", "./public/index.html")
router.GET("/api/products", productController.Index)
router.Run()
}
product.go
This file defines the Product model for the application.
package models
type Product struct {
Id int
Name string
Price float64
}
product_controller.go
This file defines a pagination function to handle incoming requests.
package controllers
import (
"app/config"
"app/models"
"net/http"
"strconv"
"github.com/gin-gonic/gin"
)
type ProductController struct {
}
func (con *ProductController) Index(c *gin.Context) {
page, _ := strconv.Atoi(c.DefaultQuery("page", "1"))
size, _ := strconv.Atoi(c.DefaultQuery("size", "10"))
order := c.DefaultQuery("order", "id")
direction := c.DefaultQuery("direction", "asc")
var products []models.Product
config.DB.Order(order + " " + direction).
Offset((page - 1) * size).
Limit(size).
Find(&products)
c.JSON(http.StatusOK, products)
}
We utilize the query string to get page, size, order, direction
information to create the paginated data by using the Limit
and Offset
method of the GORM object.
main.go
This file is the main entry point of our application. It will create and setting up the Gin web application.
package main
import (
"app/config"
"app/router"
)
func main() {
config.SetupDatabase()
router.SetupRouter()
}
index.html
Instead of entering the URL manually to test our API, we used this file to create links for easier testing.
<!DOCTYPE html>
<head>
</head>
<body>
<ul>
<li><a target="_blank" href="/api/products">Default</a></li>
<li><a target="_blank" href="/api/products?page=2">Page 2</a></li>
<li><a target="_blank" href="/api/products?page=2&size=25">Page 2 and Size 25</a></li>
<li><a target="_blank" href="/api/products?page=2&size=25&order=name">Page 2 and Size 25 and Order by name</a></li>
<li><a target="_blank" href="/api/products?page=2&size=25&order=name&direction=desc">Page 2 and Size 25 and Order by name descending</a></li>
</ul>
</body>
</html>
Run project
go run main.go
Open the web browser and goto http://localhost:8080
You will find this test page.
Testing
Testing without any parameters
Click the "Default" link, and it will open the URL http://localhost:8080/api/products
The API will return paginated data with default parameters (page = 1 and size = 10).
Page index test
Click the "Page 2" link, and it will open the URL http://localhost:8080/api/products?page=2
The API will return paginated data on the second page, starting with product id 11
Page size test
Click the "Page 2 and Size 25" link, and it will open the URL http://localhost:8080/api/products?page=2&size=25
The API will return paginated data on the second page by starting with product id 26 because the page size is 25.
Order test
Click the "Page 2 and Size 25 and Order by name" link, and it will open the URL http://localhost:8080/api/products?page=2&size=25&order=name
The API will return paginated data on the second page, but the product order is based on the product name.
Descending order test
Click the "Page 2 and Size 25 and Order by name descending" link, and it will open the URL http://localhost:8080/api/products?page=2&size=25&order=name&direction=desc
The API will return paginated data on the second page, but the product order is based on the product name in descending order.
Conclusion
In this article, you have learned how to create and setup the Gin web application in order to implement the pagination API. The pagination approach will enhance the user experience and speed up your Go API. If you like the article, please share it with your friends.
Source code: https://github.com/stackpuz/Example-Pagination-Go
Create a CRUD Web App in Minutes: https://stackpuz.com