Golang gin middleware的编写与使用 context.Next函数

这篇具有很好参考价值的文章主要介绍了Golang gin middleware的编写与使用 context.Next函数。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

中间件


在web应用服务中,完整的一个业务处理在技术上包含客户端操作、服务器端处理、返回处理结果给客户端三个步骤。

在实际的业务开发和处理中,会有更负责的业务和需求场景。一个完整的系统可能要包含鉴权认证、权限管理、安全检查、日志记录等多维度的系统支持。

鉴权认证、权限管理、安全检查、日志记录等这些保障和支持系统业务属于全系统的业务,和具体的系统业务没有关联,对于系统中的所有业务都适用。

由此,在业务开发过程中,为了更好的梳理系统架构,可以将上述描述所涉及的一些通用业务单独抽离并进行开发,然后以插件化的形式进行对接。这种方式既保证了系统功能的完整,同时又有效的将具体业务和系统功能进行解耦,并且,还可以达到灵活配置的目的。

这种通用业务独立开发并灵活配置使用的组件,一般称之为"中间件",因为其位于服务器和实际业务处理程序之间。其含义就是相当于在请求和具体的业务逻辑处理之间增加某些操作,这种以额外添加的方式不会影响编码效率,也不会侵入到框架中。中间件的位置和角色示意图如下图所示:

比如在浏览电商网站进行购买的时候要进行下单或者购买一些商品,那么需要进行登入,在对登入这个功能而言,那么很多模块都会使用到,都会使用到登入的权限。所以可以将登入的功能做成统一的模块,在需要的地方配置登入的权限,调用这个登入的功能。这样就不需要在下单购买商品的时候还需要去判断是不是已经登入了或者有没有权限。这样可以达到功能的细分,方便开发人员聚焦具体的业务逻辑,这是解耦的一种开发方式。 

Golang gin middleware的编写与使用 context.Next函数

还是下单的例子,如果最后一步是下单,那么中间有很多操作,权限操作,认证的管理等等都可以放在中间件这个地方。这样权限的认证就不需要在下单这一块写了。

那么中间件写的这一部分不仅仅下单的这个模块可以调用,其他的模块也可以调用。这就是中间件的一个作用,最后程序结束了原路的返回就行了。

由此可见中间件的作用是非常明显的。

中间件位置:位于发起请求和请求结果返回之间,请求和业务处理逻辑之间增加的操作。

中间件作用:将业务重复进行开发

 

Gin的中间件


在gin中,中间件称之为middleware,中间件的类型定义如下所示:

// HandlerFunc defines the handler used by gin middleware as return value.
type HandlerFunc func(*Context)

HandlerFunc是一个函数类型,接收一个Context参数。用于编写程序处理函数并返回HandleFunc类型,作为中间件的定义。

type   HandlerFunc   func(*Context) 其实就代表着是一个中间件。 

 

中间件Use用法


在之前学习的课程中,均使用gin.Default创建了gin引擎engine变量,其中就使用了中间件。如下图所示:

Golang gin middleware的编写与使用 context.Next函数

这里可以看到设置了两个默认的中间件,一个是日志,一个是修复,当程序发生错误的时候会返回500错误,同时将程序发生Panic的时候恢复回来。这样可以让请求比较友好一些,帮助排查服务器内部的错误。

在Default函数中,engine调用Use方法设置了Logger中间件recovery中间件。Use函数接收一个可变参数,类型为HandlerFunc,恰为中间件的类型,Use方法定义如下:

Golang gin middleware的编写与使用 context.Next函数

这个use方法接受的是可变参数有三个点,可变参数存放的类型是HandlerFunc。这样可以按照自己的自定义需求来添加任意多个中间件。

Golang gin middleware的编写与使用 context.Next函数

自定义中间件


根据上文的介绍,可以自己定义实现一个特殊需求的中间件,中间件的类型是函数,有两条标准:

  • func函数
  • 返回值类型为HandlerFunc

比如,我们自定义一个自己的中间件。在前面所学的内容中,我们在处理请求时,为了方便代码调试,通常都将请求的一些信息打印出来。有了中间件以后,为了避免代码多次重复编写,使用统一的中间件来完成。定义一个名为RequestInfos的中间件,在该中间件中打印请求的path和method,具体代码实现如下所示:

package main

import (
	"fmt"
	"github.com/gin-gonic/gin"
	"net/http"
)

func RequestInfo() gin.HandlerFunc {
	return func(context *gin.Context) {
		path := context.FullPath()
		method := context.Request.Method
		fmt.Println("请求路径为:", path, "请求方法:", method)
	}
}

func main() {
	engine := gin.Default()
	engine.Use(RequestInfo())
	engine.GET("/query", func(c *gin.Context) {
		c.JSON(http.StatusOK, map[string]interface{}{
			"code": 1,
			"msg":  c.FullPath(),
		})
	})
	engine.Run()
}

请求路径为: /query 请求方法: GET
[GIN] 2023/06/14 - 15:54:38 | 200 |     114.125µs |       127.0.0.1 | GET      "/query"

如果有多个请求,想单独的为某个接口解析来使用中间件的话,那么可以在接口解析的方法当中对其单独的使用,使用中间件作为参数传递进去。

func (group *RouterGroup) GET(relativePath string, handlers ...HandlerFunc) IRoutes
第二个是可变一类的参数
engine.GET("/get", RequestInfo(), func(context *gin.Context) {

})

上面可以看到中间件在打印的调试信息都是在请求之前打印的,也就是在接口解析之前。当某个接口解析处理之后的信息也通过中间件打印出来。

context.Next函数


通过一个例子和使用场景来说明Next函数的作用。

在上文自定义的中间件RequestInfos中,打印了请求了请求的path和method,接着去执行了正常的业务处理函数。如果我们想输出业务处理结果的信息,该如何实现呢。答案是使用context.Next函数。

context.Next函数可以将中间件代码的执行顺序一分为二,Next函数调用之前的代码在请求处理之前之前,当程序执行到context.Next时,会中断向下执行,转而先去执行具体的业务逻辑,执行完业务逻辑处理函数之后,程序会再次回到context.Next处,继续执行中间件后续的代码。

具体用法如下:

func RequestInfo() gin.HandlerFunc {
	return func(context *gin.Context) {
		path := context.FullPath()
		method := context.Request.Method
		fmt.Println("请求路径为:", path, "请求方法:", method)
		fmt.Println("状态码信息:", context.Writer.Status())

		context.Next() //这样会将func代码5行一分为二,第一部分是前面四行,执行完第一部分之后到了next
		//它就不再往下执行了,那么就会走下一个中间件的解析

		fmt.Println("状态码信息:", context.Writer.Status())
	}
}

func main() {
	engine := gin.Default()
	engine.Use(RequestInfo())
	engine.GET("/query", func(c *gin.Context) {
		c.JSON(404, map[string]interface{}{
			"code": 1,
			"msg":  c.FullPath(),
		})
		fmt.Println("handler func 业务代码")
	})
	engine.Run()
}

请求路径为: /query 请求方法: GET
状态码信息: 200
handler func 业务代码
状态码信息: 404
[GIN] 2023/06/14 - 16:37:42 | 404 |      61.458µs |       127.0.0.1 | GET      "/query"

可以看到next方法将中间件的执行分为了两个部分,这样可以方便处理后续的业务逻辑。

Golang gin middleware的编写与使用 context.Next函数文章来源地址https://www.toymoban.com/news/detail-485147.html

到了这里,关于Golang gin middleware的编写与使用 context.Next函数的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • gin 中间件流程控制:Next()、 Abort()

    源码注释: Next 应该只在中间件内部使用。它执行调用处理程序内部链中的挂起处理程序。 通俗的说,就是中间件放行,当一个中间件代码执行到 Next() ,会先执行它之后的函数,最后再来执行完本函数。 eg: 如果其中一个中间件响应了c.Abort(),后续中间件将不再执行,直接按

    2024年02月15日
    浏览(60)
  • Golang 如何基于现有的 context 创建新的 context?

    目录 基于现有的 context 创建新的 context 现有创建方法的问题 Go 1.21 中的 context.WithoutCancel 函数 Go 版本低于 1.21 该怎么办? 在 Golang 中,context 包提供了创建和管理上下文的功能。当需要基于现有的 context.Context 创建新的 context 时,通常是为了添加额外的控制信息或为了满足特

    2024年01月17日
    浏览(40)
  • golang中context详解

    编码中遇到上下文信息传递,并发信息取消等,记录下在go语言中context包的使用。 在Go语言中,context包提供了一种在程序中传递截止日期、取消信号、请求范围数据和其他元数据的方式。context包的核心类型是Context接口,它定义了在执行上下文中传递的方法。Context接口的主要

    2024年01月21日
    浏览(32)
  • golang Context应用举例

      golang标准库里Context实际上是一个接口(即一种编程规范、 一种约定)。   通过查看源码里的注释,我们得到如下约定: Done()函数返回一个只读管道,且管道里不存放任何元素(struct{}),所以用这个管道就是为了实现阻塞 Deadline()用来记录到期时间,以及是否到期。 Err()用来

    2024年02月08日
    浏览(35)
  • Golang:浅析Context包

    在golang官方文档context package - context - Go Packages中是这样介绍context包的: 在context包中定义了context类型来在不同的Goroutine 之间传递上下文,携带截止时间、取消信号以及携带上下文的系统参数(k-v)的类型。对服务器的传入请求应该创建上下文,对服务器的传出调用应该接受上

    2024年02月06日
    浏览(42)
  • golang之context实用记录

    简言 WithCancel()函数接受一个 Context 并返回其子Context和取消函数cancel 新创建协程中传入子Context做参数,且需监控子Context的Done通道,若收到消息,则退出 需要新协程结束时,在外面调用 cancel 函数,即会往子Context的Done通道发送消息 注意:当 父Context的 Done() 关闭的时候,子

    2024年02月09日
    浏览(32)
  • 【golang】Context超时控制与原理

    在Go语言圈子中流行着一句话: Never start a goroutine without knowing how it will stop。 翻译:如果你不知道协程如何退出,就不要使用它。 在创建协程时,我们可能还会再创建一些别的子协程,那么这些协程的退出就成了问题。在Go1.7之后,Go官方引入了Context来实现协程的退出。不仅

    2024年01月22日
    浏览(36)
  • SAP使用函数NUMBER_GET_NEXT创建流水号

     1. 系统中设定流水号;使用T-Code:SNRO来创建一个流  输入Object:ZLC_001,然后单击创建。 然后输入Shorttext, Long text, Number length domain在写程序的时候应该会另外创建,这里测试就使用料号的Domain MATNR来做,其他的参数使用默认值就可以了,然后保存输入的资料。 系统提示创建

    2024年02月13日
    浏览(42)
  • golang微框架Gin

    Gin是一个golang的微框架,基于httprouter,封装比较优雅,API友好,源码注释比较明确,具有快速灵活,容错方便等特点 Gin特征 速度快:基于基数树的路由,内存占用小,没有反射,可预测的APi性能 中间件支持 传入的http请求可以有中间件链和最终操作处理,例如:Logger,Aut

    2024年02月09日
    浏览(43)
  • golang Gin实现websocket

    golang使用 Gin实现 websocket,这里笔者重新搭建一个项目 项目名为 go-gin-websocket 在指定文件夹下,新建项目文件夹 go-gin-websocket 进入项目文件夹,打开cmd窗口,在项目(go-gin-websocket)文件夹路径下,执行初始化命令 go mod init go-gin-websocket 安装依赖 安装gin  安装websocket 在项

    2024年02月06日
    浏览(48)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包