学习Go语言Web框架Gee总结--中间件Middleware(五)

学习Go语言Web框架Gee总结--中间件Middleware


网站学习来源: Gee

在Go语言中,web框架的中间件是一种非常常见的概念,它允许开发人员在处理HTTP请求和响应之间插入额外的逻辑。中间件可以用于处理日志记录、身份验证、授权、错误处理等

中间件通常是一个函数,它接受一个http.Handler作为参数,并返回一个新的http.Handler。这样,当一个HTTP请求到达时,它会依次经过一系列的中间件处理,每个中间件都可以在请求被处理之前或之后执行一些额外的逻辑

首先,给context.go添加两个参数

type Context struct {// origin objectsWriter http.ResponseWriterReq    *http.Request// request infoPath   stringMethod stringParams map[string]string// response infoStatusCode int// middlewarehandlers []HandlerFuncindex    int
}

其中handlers []HandlerFunc 是一个存储了多个HandlerFunc函数的切片(slice)。HandlerFunc是一个类型,它是一个接收一个Context作为参数的函数。这意味着handlers切片中存储了多个中间件函数,每个中间件函数都可以对请求进行处理或者添加一些额外的逻辑

index int 则是用来记录当前处理到了handlers切片中的哪个中间件函数。当处理请求时,会依次调用handlers中的函数,index会记录当前调用到了哪个中间件函数,以便在处理完当前中间件后能够调用下一个中间件

通过这样的设计,可以实现在处理请求前后依次执行多个中间件函数的功能,而不需要在每个路由处理器中都编写相同的逻辑。这种设计模式使得代码更加模块化和可复用,也更容易维护

在middleware/gee/context.go中两个函数

func newContext(w http.ResponseWriter, req *http.Request) *Context {return &Context{Path:   req.URL.Path,Method: req.Method,Req:    req,Writer: w,index:  -1,}
}func (c *Context) Next() {c.index++s := len(c.handlers)for ; c.index < s; c.index++ {c.handlers[c.index](c)}
}

这两个函数是用于创建和处理上下文的中间件机制的关键部分。

首先,func newContext(w http.ResponseWriter, req http.Request) Context 函数是用来创建一个新的上下文对象的。它接受一个http.ResponseWriter和一个http.Request作为参数,然后返回一个新的Context对象。在这个函数中,我们将请求的路径、方法、请求对象和响应对象等信息存储到Context结构体中,并将index初始化为-1,表示还没有开始执行中间件

接下来,func (c *Context) Next() 函数是用来触发执行下一个中间件的。在这个函数中,我们首先将index加1,然后遍历handlers切片中的中间件函数,依次调用每个中间件函数。在调用每个中间件函数时,会将当前的上下文对象c作为参数传递进去,以便中间件函数可以对请求进行处理

通过这两个函数的配合,可以实现在处理请求时依次执行多个中间件函数的功能。当调用Next函数时,会从当前index开始,依次调用handlers中的中间件函数,直到所有的中间件函数都被执行完毕。

举个例子,定义Use函数,将中间件应用到某个 Group

// Use is defined to add middleware to the group
func (group *RouterGroup) Use(middlewares ...HandlerFunc) {group.middlewares = append(group.middlewares, middlewares...)
}func (engine *Engine) ServeHTTP(w http.ResponseWriter, req *http.Request) {var middlewares []HandlerFuncfor _, group := range engine.groups {if strings.HasPrefix(req.URL.Path, group.prefix) {middlewares = append(middlewares, group.middlewares...)}}c := newContext(w, req)c.handlers = middlewaresengine.router.handle(c)
}

首先,Use 方法是定义在 RouterGroup 结构体上的,它用于将中间件添加到特定的路由分组中。在这个方法中,我们将传入的中间件函数(HandlerFunc)添加到 group.middlewares 切片中,这样就可以将中间件与特定的路由分组关联起来

接下来,ServeHTTP 方法是 Engine 结构体的一个方法,用于处理HTTP请求。在这个方法中,我们首先创建一个空的中间件切片 middlewares。然后,我们遍历 engine.groups,也就是所有的路由分组,检查当前请求的路径是否以路由分组的前缀开头。如果是的话,就将该路由分组中的中间件添加到 middlewares 中

接着,我们创建一个新的上下文对象 c,并将刚刚收集到的中间件切片赋值给 c.handlers。最后,我们调用 engine.router.handle(c) 来处理请求,这个函数会依次执行 c.handlers 中的中间件函数

通过这种设计,我们可以将中间件与特定的路由分组进行关联,当请求到来时,会根据请求的路径自动选择合适的中间件。这样就实现了在不同的路由分组中应用不同的中间件,从而实现了更加灵活和可配置的中间件机制

关于middleware/gee/router.go中的handle函数

func (r *router) handle(c *Context) {n, params := r.getRoute(c.Method, c.Path)if n != nil {key := c.Method + "-" + n.patternc.Params = paramsc.handlers = append(c.handlers, r.handlers[key])} else {c.handlers = append(c.handlers, func(c *Context) {c.String(http.StatusNotFound, "404 NOT FOUND: %s\n", c.Path)})}c.Next()
}

handle函数是一个路由处理函数,用于根据请求的方法和路径找到对应的处理函数,并将其添加到上下文对象中的 handlers 切片中

首先,函数签名为 func (r *router) handle(c *Context),表示它是 router 结构体的一个方法,用于处理请求。它接受一个指向 Context 对象的指针作为参数

在函数体内部,首先调用 r.getRoute(c.Method, c.Path) 来根据请求的方法和路径获取对应的路由节点(n)和参数(params)。这个方法会返回匹配的路由节点以及路径参数

接着,通过判断 n 是否为空来确定是否找到了匹配的路由。如果找到了匹配的路由节点,就将 c.Params 设置为获取到的参数,并根据请求方法和路由模式拼接出一个唯一的 key。然后将对应的处理函数(r.handlers[key])添加到 c.handlers 切片中

如果未找到匹配的路由节点,就将一个默认的处理函数添加到 c.handlers 中,该处理函数返回404 Not Found的错误信息

最后,调用 c.Next() 来触发执行下一个中间件

总的来说,这段代码的作用是根据请求的方法和路径找到对应的处理函数,并将其添加到上下文对象中的 handlers 切片中。这样在处理请求时,就可以依次执行这些处理函数,实现请求的处理逻辑

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/602631.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Linux驱动学习—中断

1、中断基础概念 1.1 什么是中断 CPU在正常运行期间&#xff0c;由外部或者内部引起的时间&#xff0c;让CPU停下当前正在运行的程序&#xff0c;转而去执行触发他的中断所对应的程序&#xff0c;这就是中断。 响应中断的过程&#xff1a; <1>中断请求 <2>中断…

windows10下重置mysql8的root密码

控制台A启动mysql: mysqld --defaults-file“D:\program\phpstudy_pro\Extensions\MySQL8.0.12\my.ini” --console --skip-grant-tables --shared-memory 控制台B连接并清空密码&#xff1a; mysql -uroot -p -P3308 use mysql; update user set authentication_string‘’ w…

三、C语言中的分支与循环—for循环 (6)

本章分支结构的学习内容如下&#xff1a; 三、C语言中的分支与循环—if语句 (1) 三、C语言中的分支与循环—关系操作符 (2) 三、C语言中的分支与循环—条件操作符 与逻辑操作符(3) 三、C语言中的分支与循环—switch语句&#xff08;4&#xff09;分支结构 完 本章循环结构的…

JavaScript基本语法

文章目录 1. JavaScript 是什么1.1 JavaScript 和 HTML 和 CSS 之间的关系1.2 JavaScript 运行过程1.3 JavaScript 的组成 2. JavaScript 的书写形式2.1 行内式2.2 内嵌式2.3 外部式 3. 变量的使用3.1 静态变量和动态变量 4. 基本数据类型4.1 undefined 未定义数据类型4.2 null…

2.3_6 用信号量实现进程互斥、同步、前驱关系

2.3_6 用信号量实现进程互斥、同步、前驱关系 #mermaid-svg-fj0wp6tJGfadcT8h {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-fj0wp6tJGfadcT8h .error-icon{fill:#552222;}#mermaid-svg-fj0wp6tJGfadcT8h .error-t…

ENVI 各版本安装指南

ENVI下载链接 https://pan.baidu.com/s/1APpjHHSsrXMaCcJUQGmFBA?pwd0531 1.鼠标右击【ENVI 5.6(64bit&#xff09;】压缩包&#xff08;win11及以上系统需先点击“显示更多选项”&#xff09;选择【解压到 ENVI 5.6(64bit&#xff09;】。 2.打开解压后的文件夹&#xff0c…

mysql基础-数据操作之增删改

目录 1.新增数据 1.1单条数据新增 1.2多条数据新增 1.3查询数据新增 2.更新 2.1单值更新 2.2多值更新 2.3批量更新 2.3.1 批量-单条件更新 2.3.2批量-多条件更新 2.4 插入或更新 2.5 联表更新 3.删除 本次分享一下数据库的DML操作语言。 操作表的数据结构&#xf…

Explain详解与索引最佳实践

听课问题(听完课自己查资料) type中常用类型详细解释 null <- system <- const <- er_ref <- ref <- range <- index <- all Explain 各列解释 EXPLAIN SELECT* FROMactorLEFT JOIN film_actor ON actor_id actor.id; 1. id 代表执行的先后顺序 比如…

前端优化之一:dns预获取 dns-prefetch 提升页面载入速度

问题&#xff1a;怎么做到dns域解析&#xff1f; 用于优化网站页面的图片 问题&#xff1a;怎么提升网站性能&#xff1f; dns域解析&#xff0c;是提升网站的一个办法。 DNS Prefetch&#xff0c;即DNS预获取&#xff0c;是前端优化的一部分。 一般来说&#xff0c;在前端…

Python笔记01-你好Python

文章目录 Python简介环境安装Hello world开发工具 Python简介 python的诞生 1989年&#xff0c;为了打发圣诞节假期&#xff0c;Gudio van Rossum吉多 范罗苏姆&#xff08;龟叔&#xff09;决心开发一个新的解释程序&#xff08;Python雏形&#xff09; 1991年&#xff0c;第…

深度学习|交叉熵

文章目录 什么是交叉熵如何构造信息量的函数关于 C 1 C_1 C1​参数的选择关于 C 2 C_2 C2​参数的选择 一个系统的熵如何比较两个系统的熵交叉熵在神经网络中的应用参考 什么是交叉熵 熵是用来衡量一个系统的混乱程度&#xff0c;混乱程度也其实代表着整个系统内部的不确定性。…

C语言浮点型详解

1. 浮点型变量介绍 1.1 类型概览 浮点型变量用于存储小数数值&#xff0c;C语言提供了三种主要的浮点数类型&#xff1a;单精度浮点型&#xff08;float&#xff09;、双精度浮点型&#xff08;double&#xff09;、长双精度浮点型&#xff08;long double&#xff09;。 类…

听GPT 讲Rust源代码--compiler(15)

File: rust/compiler/rustc_arena/src/lib.rs 在Rust源代码中&#xff0c;rustc_arena/src/lib.rs文件定义了TypedArena&#xff0c;ArenaChunk&#xff0c;DroplessArena和Arena结构体&#xff0c;以及一些与内存分配和容器操作相关的函数。 cold_path<F: FnOnce,drop,new,…

MySQL 8.0中新增的功能(三)

字符集支持 默认字符集已从latin1更改为utf8mb4。utf8mb4字符集新增了几个排序规则&#xff0c;包括utf8mb4_ja_0900_as_cs&#xff0c;这是MySQL中首个用于Unicode的日语特定排序规则。 JSON增强功能 MySQL的JSON功能性方面进行了以下增强或添加&#xff1a; ->> &a…

解决 POST http://x.x.x.x:8000/aaa/ net::ERR_CONNECTION_TIMED_OUT

记录一下我遇到的问题和解决办法 我的项目前后端分离&#xff0c;在前端用的vue访问后端时连接不上后端&#xff0c;一切操作都触发不了后端&#xff0c;数据也传不到后端去&#xff1b; 原因&#xff1a;url有问题&#xff0c;url地址写的不是本机&#xff0c;所以导致连接超…

vector_01_使用vector第一步是什么?

C 中使用vector来存储数据&#xff0c;其打开方式是什么&#xff1f; 开始第一步&#xff0c;定义一个vector类型的变量&#xff0c;try 一try。 #include <iostream> #include <utility> // #include <vector> /*先注释&#xff0c;编译器会报什么错误&am…

UE5.1_UMG序列帧动画制作

UE5.1_UMG序列帧动画制作 UMG序列帧动画制作相对比较简单&#xff0c;不像视频帧需要创建媒体播放器那么复杂&#xff0c;以下简要说明&#xff1a; 1. 事件函数 2. 准备序列帧装入数组 3. 构造调用事件函数 4. 预览 序列帧UMG0105 5. 完成&#xff01;按需配置即可。

MySQL之数据类型建表以及约束

SELECT(查询) 查询操作用于从数据库中检索数据 查询可以基于不同的条件&#xff0c;如字段值、范围、排序等 查询结果可以返回单个记录或多个记录 查询指定列 select 列名 from 表名 列名&#xff1a;代表从指定的列名中查找 , 如果是查找对应的多列&#xff0c;则用英文…

uniapp知识大杂烩?

UniApp是一个基于Vue.js框架的跨平台开发框架&#xff0c;可以用于同时开发iOS、Android和Web应用程序。下面是一些UniApp的知识点大杂烩&#xff1a; 跨平台开发&#xff1a;UniApp采用了一套代码多端运行的原则&#xff0c;可以使用一种语言&#xff08;通常是Vue.js&#xf…

【鸿蒙4.0】安装DevEcoStudio

1.下载安装包 HUAWEI DevEco Studio和SDK下载和升级 | HarmonyOS开发者华为鸿蒙DevEco Studio是面向全场景的一站式集成开发环境,&#xff0c;在鸿蒙官网下载或升级操作系统开发工具DevEco Studio最新版本&#xff0c;SDK配置和下载&#xff0c;2.1支持Mac、Windows操作系统。…