85 phút
REST API với Gin Framework
Giới thiệu Gin
Gin là web framework hiệu suất cao cho Go.
Cài đặt
go get -u github.com/gin-gonic/gin
Ứng dụng cơ bản
package main
import "github.com/gin-gonic/gin"
func main() {
r := gin.Default()
r.GET("/ping", func(c *gin.Context) {
c.JSON(200, gin.H{
"message": "pong",
})
})
r.Run(":8080")
}
Routing
HTTP Methods
r.GET("/users", getUsers)
r.POST("/users", createUser)
r.PUT("/users/:id", updateUser)
r.DELETE("/users/:id", deleteUser)
r.PATCH("/users/:id", patchUser)
Route groups
v1 := r.Group("/api/v1")
{
v1.GET("/users", getUsers)
v1.POST("/users", createUser)
}
auth := v1.Group("/admin")
auth.Use(AuthMiddleware())
{
auth.GET("/stats", getStats)
}
Request Handling
Path parameters
r.GET("/users/:id", func(c *gin.Context) {
id := c.Param("id")
c.JSON(200, gin.H{"id": id})
})
Query parameters
r.GET("/search", func(c *gin.Context) {
q := c.Query("q")
page := c.DefaultQuery("page", "1")
c.JSON(200, gin.H{"q": q, "page": page})
})
JSON binding
type CreateUserRequest struct {
Name string `json:"name" binding:"required"`
Email string `json:"email" binding:"required,email"`
Age int `json:"age" binding:"gte=0,lte=150"`
}
r.POST("/users", func(c *gin.Context) {
var req CreateUserRequest
if err := c.ShouldBindJSON(&req); err != nil {
c.JSON(400, gin.H{"error": err.Error()})
return
}
c.JSON(201, req)
})
Middleware
Custom middleware
func AuthMiddleware() gin.HandlerFunc {
return func(c *gin.Context) {
token := c.GetHeader("Authorization")
if token == "" {
c.AbortWithStatusJSON(401, gin.H{"error": "unauthorized"})
return
}
c.Set("userID", 123)
c.Next()
}
}
CORS
import "github.com/gin-contrib/cors"
r.Use(cors.Default())
Project Structure
myapi/
├── main.go
├── go.mod
├── internal/
│ ├── handlers/
│ │ └── user.go
│ ├── models/
│ │ └── user.go
│ ├── services/
│ │ └── user.go
│ ├── repositories/
│ │ └── user.go
│ └── middleware/
│ └── auth.go
└── pkg/
└── database/
└── db.go
Full Example
Model
package models
import "time"
type User struct {
ID uint `json:"id" gorm:"primaryKey"`
Name string `json:"name" binding:"required"`
Email string `json:"email" binding:"required,email" gorm:"unique"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
}
Handler
package handlers
import (
"net/http"
"github.com/gin-gonic/gin"
"myapi/internal/models"
)
type UserHandler struct {
// dependencies
}
func (h *UserHandler) GetUsers(c *gin.Context) {
users := []models.User{}
c.JSON(http.StatusOK, users)
}
func (h *UserHandler) CreateUser(c *gin.Context) {
var user models.User
if err := c.ShouldBindJSON(&user); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
c.JSON(http.StatusCreated, user)
}
Main
package main
import (
"github.com/gin-gonic/gin"
"myapi/internal/handlers"
)
func main() {
r := gin.Default()
userHandler := &handlers.UserHandler{}
api := r.Group("/api/v1")
{
users := api.Group("/users")
{
users.GET("", userHandler.GetUsers)
users.POST("", userHandler.CreateUser)
users.GET("/:id", userHandler.GetUser)
users.PUT("/:id", userHandler.UpdateUser)
users.DELETE("/:id", userHandler.DeleteUser)
}
}
r.Run(":8080")
}
Bài tập thực hành
Hãy tạo REST API hoàn chỉnh cho quản lý sản phẩm!