1.middleware

在 Web 开发中,Gin 是一个流行的 Go 言语结构,它供给了一种简练且高效的方式来构建 Web 运用程序。Gin 中的中间件是一种用于处理 HTTP 恳求和呼应的机制。中间件答应开发者在恳求到达处理程序之前或呼应发送到客户端之前,对恳求和呼应进行一些预处理或后处理。

在 Gin 中,中间件是经过运用 Use 办法来注册的。这个办法接受一个或多个中间件函数作为参数。中间件函数在恳求被处理之前被调用,并且能够履行一些操作,例如记载恳求日志、鉴权、恳求参数验证等。中间件函数还能够修改恳求或呼应,或许在恳求处理之后履行一些清理操作。

1.1运用办法

在 Gin 结构中,中间件是用于在恳求到达路由处理程序之前或之后履行一些操作的函数。它们能够用于增加日志记载、身份验证、过错处理等功用。下面是 Gin 中间件的运用办法介绍:

  1. 大局中间件:运用Use办法将中间件增加到大局中,对所有的路由恳求都起作用。
r := gin.Default()
r.Use(loggerMiddleware)
  1. 路由中间件:运用Group办法创建具有相同中间件的路由组。
authGroup := r.Group("/api", authMiddleware)
authGroup.GET("/users", getUsers)
authGroup.POST("/users", createUser)
  1. 单个路由中间件:在路由处理程序上运用Use办法增加中间件。
r.GET("/hello", authMiddleware, helloHandler)
  1. 中间件函数签名:中间件函数有必要具有func(c *gin.Context)的签名,其间c *gin.Context是恳求的上下文目标,它包括了恳求和呼应的相关信息。
func loggerMiddleware(c *gin.Context) {
    // 在处理恳求之前履行的操作
    log.Printf("Started %s %s", c.Request.Method, c.Request.URL.Path)
    // 将恳求传递给下一个处理程序
    c.Next()
    // 在处理完恳求之后履行的操作
    log.Printf("Completed %s in %v", c.Request.URL.Path, time.Since(start))
}
  1. 中间件的履行次序:中间件按照它们增加的次序履行,因此次序很重要。能够运用Use办法多次增加不同的中间件,它们将按照增加的次序顺次履行。
r := gin.Default()
r.Use(loggerMiddleware)
r.Use(authMiddleware)
  1. 中间件中的操作:在中间件函数中,你能够履行各种操作,例如记载日志、验证身份、修改恳求或呼应等。如果需要停止处理链并回来呼应,能够运用c.Abort()办法。
func authMiddleware(c *gin.Context) {
    token := c.GetHeader("Authorization")
    if token != "valid_token" {
        c.JSON(http.StatusUnauthorized, gin.H{"error": "Invalid token"})
        c.Abort()
        return
    }
    c.Next()
}

经过运用这些办法,你能够运用中间件增加额外的功用、处理恳求和呼应,并根据需要在不同的路由上运用不同的中间件。这使得 Gin 结构非常灵活和强壮。

1.2快速开端

以下是一个运用了Gin中间件的完好代码示例:

package main
import (
	"log"
	"net/http"
	"time"
	"github.com/gin-gonic/gin"
)
func main() {
	r := gin.Default()
	// 大局中间件
	r.Use(loggerMiddleware)
	// 路由组中间件
	authGroup := r.Group("/api")
	authGroup.Use(authMiddleware)
	{
		authGroup.GET("/users", getUsers)
		authGroup.POST("/users", createUser)
	}
	// 单个路由中间件
	r.GET("/hello", authMiddleware, helloHandler)
	r.Run(":8080")
}
func loggerMiddleware(c *gin.Context) {
	start := time.Now()
	// 在处理恳求之前履行的操作
	log.Printf("Started %s %s", c.Request.Method, c.Request.URL.Path)
	// 将恳求传递给下一个处理程序
	c.Next()
	// 在处理完恳求之后履行的操作
	log.Printf("Completed %s in %v", c.Request.URL.Path, time.Since(start))
}
func authMiddleware(c *gin.Context) {
	token := c.GetHeader("Authorization")
	if token != "valid_token" {
		c.JSON(http.StatusUnauthorized, gin.H{"error": "Invalid token"})
		c.Abort()
		return
	}
	c.Next()
}
func getUsers(c *gin.Context) {
	// 处理获取用户列表的逻辑
	c.JSON(http.StatusOK, gin.H{
		"message": "Get users",
	})
}
func createUser(c *gin.Context) {
	// 处理创建用户的逻辑
	c.JSON(http.StatusOK, gin.H{
		"message": "Create user",
	})
}
func helloHandler(c *gin.Context) {
	c.JSON(http.StatusOK, gin.H{
		"message": "Hello, World!",
	})
}

在这个示例中:

  1. loggerMiddleware是一个大局中间件,它记载恳求的开端和完毕时间。
  2. authMiddleware是一个路由组中间件,它用于验证恳求的token。
  3. /api/users/api/users是归于authGroup路由组的路由,它们都将运用authMiddleware中间件。
  4. /hello是一个独自的路由,它运用了authMiddleware中间件。

当你启动运用程序后,能够运用不同的恳求来测验中间件的作业原理。例如:

  • 对于没有供给有用token的恳求,将回来401 Unauthorized:
GET /api/users
Authorization: invalid_token
  • 对于供给了有用token的恳求,将回来相应的处理结果:
GET /api/users
Authorization: valid_token
POST /api/users
Authorization: valid_token
GET /hello
Authorization: valid_token

经过运用这些不同的中间件办法,能够在 Gin 运用程序中增加各种功用。

2.Gin验证器

Go的Validator是一种用于验证数据有用性的库或软件包。它供给了一组验证规则和函数,用于确保输入数据符合特定的要求和束缚。经过运用验证器,您能够轻松地验证表单输入、API恳求、装备参数等。

在Go言语中,有许多可用的验证库,其间一些受欢迎的包括:

  1. govalidator:github.com/asaskevich/…
  2. validator:github.com/go-playgrou…
  3. ozzo-validation:github.com/go-ozzo/ozz…

本文介绍第二种validator,具体的运用指南能够参考官网文档pkg.go.dev/github.com/…

2.1快速开端

这段代码是一个运用 Gin 结构和 go-playground/validator 进行参数验证的示例。

在这段代码中,咱们定义了一个 User 结构体,它包括了 NameEmailAge 字段,每个字段都运用了 jsonvalidate 标签来指定 JSON 序列化的字段名和验证规则。

然后,咱们创建了一个 Gin 路由器,并注册了一个名为 “/user” 的 POST 路由。

在中间件函数 ValidatorMiddleware 中,咱们创建了一个 go-playground/validator 的实例,并将其存储到 Gin 上下文中,以便在后续的处理函数中运用。

在处理函数 handleUser 中,咱们首先从 Gin 上下文中获取验证器实例,并运用 c.ShouldBindJSON 办法将恳求的 JSON 数据绑定到 user 结构体中。

然后,咱们运用验证器对 user 结构体进行验证,如果验证失利,咱们回来相应的验证过错呼应。

如果验证经过,咱们能够进一步处理恳求,并回来一个包括成功信息和用户数据的 JSON 呼应。

package main
import (
    "github.com/gin-gonic/gin"
    "github.com/go-playground/validator/v10"
    "net/http"
)
type User struct {
    Name  string `json:"name" validate:"required"`
    Email string `json:"email" validate:"email" `
    Age   int    `json:"age" validate:"gte=0,lte=150"`
}
func main() {
    r := gin.Default()
    // 注册自定义验证器中间件
    r.Use(ValidatorMiddleware())
    r.POST("/user", handleUser)
    r.Run(":8090")
}
func ValidatorMiddleware() gin.HandlerFunc {
    return func(c *gin.Context) {
        validate := validator.New()
        // 将验证器存储到 Gin 上下文中
        c.Set("vd", validate)
        c.Next()
    }
}
func handleUser(c *gin.Context) {
    // 从 Gin 上下文中获取验证器
    vd, exists := c.Get("vd")
    if !exists {
        c.JSON(http.StatusInternalServerError, gin.H{"error": "Validator not found"})
        return
    }
    // 运用验证器进行参数验证
    var user User
    if err := c.ShouldBindJSON(&user); err != nil {
        c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
        return
    }
    err := vd.(*validator.Validate).Struct(user)
    if err != nil {
        c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
        return
    }
    // 处理验证经过的逻辑
    c.JSON(http.StatusOK, gin.H{"message": "User registered successfully", "user": user})
}

当咱们输入一个过错的邮箱,恳求会被阻拦,并回来下图信息:

【Gin实战二】Gin中间件和Go Validator:Web开发中的秘密武器