Gin第七天
Gin的中间件,或者说web框架中的中间件是提供系统软件和应用软件之间连接的软件。这些中间件可以是第三方的,也可以是自定义的,它们可以为web程序添加功能,也可以多处复用。
在使用Gin创建路由的时候,我们经常会用到gin.Default()
,其实这个之前就提到过,它默认就使用了Logger()和Recovery()这两个中间件。
如果不想使用这两个可以直接使用gin.New()
,其实一般情况下这两种差别不大。今天就主要讲讲Gin中关于中间件的使用问题,其中中间件又可以分为全局中间件和局部中间件。
1. 全局中间件
全局中间件就是整个项目中都可以随处调用,所有请求都要经过这个中间件。
我们可以写一个计时中间件的例子
package main import ( "fmt" "github.com/gin-gonic/gin" "time" ) func MiddleWare() gin.HandlerFunc{ return func(c *gin.Context) { t:=time.Now() fmt.Println("全局中间件开始") c.Set("request","中间件") c.Next() status:=c.Writer.Status() fmt.Println("中间件执行完毕",status) t2:=time.Since(t) fmt.Println("耗时:",t2) } } func main(){ r:=gin.Default() r.Use(MiddleWare()) r.GET("test", func(c *gin.Context) { req,_:=c.Get("request") fmt.Println("request:",req) c.JSON(200,gin.H{"request":req}) }) r.Run() } 复制代码
可以看到,全局中间件通过r.Use()
方法设置,所以最简单的例子
r:=gin.Default() r:=gin.New() r.Use(Logger(),Recovery()) 复制代码
上面两种写法实际上是等价的,这从源码中也可以看出来。
设置完中间件,在中间件中如果要传递数据那么就需要使用到gin.Context
中的set、get方法,将数据存放到Context中进行传递。
2. 局部中间件
局部中间件就只有相对应的作用域中使用,只有相应路由请求才会使用到这个中间件。
同样的,也是写一个例子
package main import ( "fmt" "github.com/gin-gonic/gin" "time" ) func MiddleWare1() gin.HandlerFunc{ return func(c *gin.Context) { t:=time.Now() fmt.Println(c.Request.URL.Path+"局部中间件开始") c.Set("request","中间件") c.Next() status:=c.Writer.Status() fmt.Println("局部中间件执行完毕",status) t2:=time.Since(t) fmt.Println("耗时:",t2) } } func main(){ r:=gin.Default() r.GET("test",MiddleWare1(), func(c *gin.Context) { req,_:=c.Get("request") fmt.Println("request:",req) c.JSON(200,gin.H{"request":req}) }) r.Run() } 复制代码
我自定义了一个计时中间件,但是这次我不想全局设置,而是只用于个别路由,那么设置方式就有所改变。
Gin中已经将所有的请求参数设为可变参数,也就是说除了路由,后面可以有很多处理器函数,中间件其实也就是一种处理器函数,所以我们可以像上面的例子一样,将局部中间件作为参数设置到对应的路由请求中,当然也可以像下面这种
r.GET(...).Use(MiddleWare1())
源码中同样为路由组写了接口,所有路由请求都可以使用Use()方法,本质上其实就是使用append将路由组中的处理器函数进行添加然后返回新的路由组。
3. 案例+写入日志文件
有了上面的了解,我们就可以模拟一下中间件的使用,同时会涉及一些日志文件写入的问题。
package main import ( "fmt" "github.com/gin-gonic/gin" "io" "os" "time" ) func myMiddle(c *gin.Context){ s:=time.Now() c.Next() e:=time.Since(s) fmt.Println("耗时:",e) } func handler1(c *gin.Context){ time.Sleep(1*time.Second) c.JSON(200,gin.H{"handler1":"完成"}) } func handler2(c *gin.Context){ time.Sleep(2*time.Second) c.JSON(200,gin.H{"handler2":"完成"}) } func main(){ f,_:=os.Create("demo.log") gin.DefaultWriter=io.MultiWriter(f,os.Stdout) r:=gin.Default() r.Use(myMiddle) Group:=r.Group("/test") { Group.GET("/test1",handler1) Group.GET("/test2",handler2) } r.Run() } 复制代码
这里设置了两个handler来模拟一些请求事件,然后依然是一个计时中间件,但是在主函数中首先创建了一个log文件来记录日志,然后将输出流和文件流同时作为Gin的输出方式,全局注册中间件之后启动服务,访问一下不同路由。
这样就可以将日志记录在文件中。
结束
今天主要讲了在Gin中使用中间件,其实最近在学习fastapi中最大的兴奋之处还不是惊讶于python的异步框架性能能达到这种程度,而是服务启动后在/docs中可以直接查看api接口并且可以简单测试这个功能,对于前后端分离调用接口的时候感觉很舒服,还有一点关于Vue组件的东西没弄完,过年继续。