内容来自:Golang公开课(8):月经面试题之gin的中间件原理和简单手撸_哔哩哔哩_bilibili
一、go洋葱模型图
二、中间件模拟示例代码
package main
import "fmt"
type Context struct {
handlers []func(c *Context) // 保存handler函数的切片
index int8 //记录handler切片的当前位置
}
// Use 将一个要执行的handler函数放到 handlers切片中
func(this *Context) Use(f func(c *Context)) {
this.handlers = append(this.handlers,f)
}
// Get 将一个要执行的handler函数放到 handlers切片中
func(this *Context) Get(path string,f func(c *Context)){
this.handlers = append(this.handlers,f)
}
// Next 执行handlers 切片列表中的下一个handler函数
func(this *Context) Next() {
this.index++
this.handlers[this.index](this) //剥洋葱的下一层
}
// Run 启动开始执行 handlers切片中第一个 handler函数
func(this *Context) Run() {
this.handlers[0](this) //剥洋葱,第一层
}
func main() {
c := &Context{}
c.Use(Middleware1())
c.Use(Middleware2())
c.Get("/", func(c *Context) {
fmt.Println("Get handlerfunc run")
})
c.Run()
}
// Middleware1 中间件函数 返回一个带有具体业务的handler函数
func Middleware1() func(c *Context) {
return func(c *Context) {
fmt.Println("middl1 --- start")
c.Next() //执行下一个handler函数
fmt.Println("middl1 --- end")
}
}
// Middleware2 中间件函数 返回一个带有具体业务的handler函数
func Middleware2() func(c *Context) {
return func(c *Context) {
fmt.Println("middl2 --- start")
c.Next() //执行下一个handler函数
fmt.Println("middl2 --- end")
}
}
执行结果:
三、理解代码实现
1. Context对象可以保存 可执行的handler函数列表
2.Use函数执行的目的是将 某个可执行的handler函数追加到函数列表中,而这追加的函数里携带有 Next函数。 按照程序执行顺序,那么其意思是执行某个函数的一半时,在中间插入一段另一个函数的执行,如果另一个函数执行完,那么就继续执行当前函数后半段。 如下代码示例:
package main
import "fmt"
func main() {
F1()
}
func F1() {
fmt.Println("F1 start")
// Next() 执行下一个函数(相当于F1中间插入一段代码)
F2()
fmt.Println("F1 end")
}
func F2() {
fmt.Println("F2 start")
fmt.Println("F2 end")
}
执行结果:
3.Get函数,则是没有Next()执行的函数,即洋葱的最中间,handlers列表中最后一个函数了,执行完后则逐步执行上一个函数的后半段,一层层返回到外面