中间件 | 青训营

166 阅读3分钟

中间件设计

Next()

常用于中间链中,把控制权传递给下一个中间件。 实现预处理和后处理

func Middleware1(next func()) {
    fmt.Println("Before Middleware 1")
    next()
    fmt.Println("After Middleware 1")
}

func Middleware2(next func()) {
    fmt.Println("Before Middleware 2")
    next()
    fmt.Println("After Middleware 2")
}

func FinalHandler() {
    fmt.Println("Final Handler")
}

func main() {
    // 构建中间件链
    middlewareChain := Middleware1(Middleware2(FinalHandler))

    // 执行中间件链
    middlewareChain()
}

输出的结果如下:

Before Middleware 1
Before Middleware 2
Final Handler
After Middleware 2
After Middleware 1

自动处理

用户不主动调用下一个函数时的处理

示例如下:

fun(ctx *RequsestContext) Next(){
	ctx.index++
	for ctx.index < int8(len(ctx.handlers)){
		ctx.handlers[ctx.index]()
		ctx.index++
	}
}

解释如下

这段代码看起来是一个中间件处理函数中的部分代码,用于实现中间件链中的控制流程。让我们逐步解释它:

  1. fun(ctx *RequestContext) Next():这是一个函数定义,接收一个名为ctx的指向RequestContext结构体的指针作为参数。Next()是函数名,表明这是一个用于控制中间件链流程的函数。
  2. ctx.index++ctx应该是一个保存中间件链状态的结构体,index可能是其中的一个字段,用于跟踪当前处理到了中间件链中的第几个中间件。
  3. for ctx.index < int8(len(ctx.handlers)):这是一个循环条件,表示当ctx.index小于中间件链中中间件的数量时,继续循环执行下面的代码。
  4. ctx.handlers[ctx.index]():这一行代码执行当前索引所指向的中间件函数。ctx.handlers应该是一个保存中间件函数的切片,ctx.index作为索引指示当前要执行的中间件函数。
  5. ctx.index++:在执行完当前中间件函数后,ctx.index递增,准备执行下一个中间件。
  6. 整个循环会重复执行,直到ctx.index超过中间件切片的长度,也就是所有中间件都被执行完毕。

异常处理

示例如下:

func (ctx *RequsestCOntext) Abort(){
    ctx.index = IndexMax
}
  1. ctx.Abort()RequestContext 结构体的一个方法。Abort() 的目的是将 ctx.index 设置为一个特殊的值 IndexMax,以表示请求处理过程中的中间件链应该立即中止,不再继续执行后续中间件。
  2. IndexMax 可能是一个在代码中预定义的常量或枚举值,用于表示一个不可能达到的索引值。通常,IndexMax 的值会设置得非常大,确保它超出了中间件切片的有效索引范围。
  3. ctx.index 的值被设置为 IndexMax 后,for 循环中的条件 ctx.index < int8(len(ctx.handlers)) 将不再成立,即循环条件不满足,从而导致中间件链的执行被中止。

Gin中使用

Gin是一种用于构建Web应用程序的Golang(Go语言)框架,它也具有中间件的功能。

package main
import (
	"github.com/gin-gonic/gin"
)
//中间件1
func LoggerMiddleware() gin.HandlerFunc {
	return func(c *gin.Context) {
		// 在请求到达处理程序之前记录或处理请求的逻辑
		println("Logging request before handling...")
		c.Next() // 继续到下一个处理程序
	}
}
//中间件2
func AuthMiddleware() gin.HandlerFunc {
	return func(c *gin.Context) {
		// 认证授权的逻辑
		println("Authentication middleware...")
		c.Next() // 继续到下一个处理程序
	}
}

func main() {
    //分配默认的路由
	router := gin.Default()
	// 添加中间件到“过滤器链”
    // 按照添加顺序执行中间件
	router.Use(LoggerMiddleware())
	router.Use(AuthMiddleware())

	router.GET("/hello", func(c *gin.Context) {
		c.String(200, "Hello, Gin!")
	})

	router.Run(":8080")
}

/**
	Logging request before handling...
	Authentication middleware...
*/