首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >go语言中利用函数闭包实现中间件

go语言中利用函数闭包实现中间件

原创
作者头像
言志志
修改于 2023-10-10 12:46:34
修改于 2023-10-10 12:46:34
1.1K3
举报
文章被收录于专栏:Go语言学习笔记Go语言学习笔记

前言

本文是探讨的是"go语言中的中间件"

此文章是个人学习归纳的心得, 如有不对, 还望指正, 感谢!

判断

为了判断你是否有阅读本文的必要,请你在脑海中快速实现一个中间件的代码结构?

什么叫做中间件?

中间件设计模式是一种常见的软件设计模式,它在许多编程语言和框架中被广泛应用,包括Go、Node.js、Python等。

中间件模式的核心思想是将一系列的处理逻辑组合在一起,形成一个处理链(或称为管道),每个处理逻辑被封装成一个中间件函数。每个中间件函数可以在请求处理的不同阶段添加额外的功能或逻辑,而无需修改原始的处理函数。

中间件模式的优势在于它提供了一种可插拔、可组合的方式来扩展和定制请求处理过程。以下是中间件模式的一些关键特点:

  1. 可插拔性(Pluggability):中间件模式允许将中间件函数插入到处理链中,以添加新的功能或逻辑。这种可插拔性使得我们可以根据需要动态地添加、移除或替换中间件,而无需修改原始的处理函数。
  2. 复用性(Reusability):中间件模式可以将通用的功能或逻辑封装成可复用的中间件函数。这些中间件函数可以在不同的请求处理中重复使用,提高了代码的复用性。
  3. 可组合性(Composability):中间件模式允许将多个中间件函数按照特定的顺序组合在一起,形成一个处理链。每个中间件函数可以在调用原始处理函数之前、之后或两者之间执行自己的逻辑。这种可组合性使得我们可以构建复杂的处理逻辑,将各个中间件函数按需组合,形成一个完整的请求处理流程。
  4. 责任链(Chain of Responsibility):中间件模式的处理链形成了一个责任链结构,每个中间件函数都有机会处理请求或将处理传递给下一个中间件。这种责任链结构可以根据实际需求动态调整中间件的顺序,实现不同的处理流程。

中间件模式在Web开发中得到了广泛应用,特别是在处理HTTP请求的过程中。常见的中间件功能包括身份验证、日志记录、请求解析、缓存、错误处理、压缩等。通过将这些功能封装成中间件函数,并按照需要组合起来,我们可以轻松地构建灵活、可扩展的Web应用程序。

利用函数闭包实现一个简单的中间件

下面我以求两数之和为例,实现一个简单的中间件,可以看如下代码

代码语言:go
AI代码解释
复制
package main



import "log"



func sum(a, b int) int {

   return a + b

}



func Zh(f func(a, b int) int) func(a, b int) int {

   return func(a, b int) int {

      log.Printf("日志中间件,记录操作数: a: %d b: %d\n", a, b)

      return f(a, b)

   }

}



func main(){



   addWithLogging := Zh(sum)

   

   result := addWithLogging(2, 3)



   result2 := addWithLogging(5, 6)



   fmt.Println(result,result2)



}

上面的代码,可以被认为是一个中间件函数的实现,我们在sum函数执行之前,先进行了日志的记录,并且又不影响原函数的执行,就像添加了一个过程一样,这个中间件函数可以被插入到处理链中,在执行原始函数之前记录操作数的日志,其实你可以发现,我不过就是相当于将传入的函数进行封装了一下

当然,我们还可以更加优雅,那就是抽象为一个函数类型,并且我们可以发现,Zh中间件处理后的返回值,还可以继续被它处理。

代码语言:go
AI代码解释
复制
// 优雅地处理

type F func(func(a, b int) int

对了,上面的函数是利用闭包实现的,首先闭包是指函数内部定义的函数可以访问其外部函数的变量。

而在这个例子中,匿名函数func(a, b int) int是在Zh函数内部定义的,并且可以访问外部函数的参数f

具体来说,Zh函数接受一个函数类型的参数f,并返回一个具有相同函数签名的函数。在返回的函数内部,它使用了log.Printf打印日志,并调用了外部函数的参数f

由于返回的函数是在Zh函数内部定义的,它可以访问Zh函数的参数f,即使Zh函数已经执行完毕并返回了。这是因为闭包函数捕获了其外部函数的变量,形成了一个闭包环境,使得返回的函数仍然可以访问外部函数的变量。

当然,我只是想通过这个简单的样例让你知道,什么是中间件

像go中的gin框架中的中间件的使用就很成熟,gin巧妙的把具体实现过程进行了隐藏,让你只要写好一个函数,然后插入使用即可,非常优雅,而本文的样例,其实是把隐藏的过程进行了展示,详情请看gin的源码。

我正在参与2023腾讯技术创作特训营第二期有奖征文,瓜分万元奖池和键盘手表

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
3 条评论
热度
最新
所以中间件就是对本来要做的事,进行了封装?
所以中间件就是对本来要做的事,进行了封装?
221举报
也可以这么理解
也可以这么理解
回复回复点赞举报
貌似是的
貌似是的
回复回复点赞举报
推荐阅读
编辑精选文章
换一批
JavaScript——ES6新增语法特性
ES的全称是ECMAScript,它是由ECMA国际标准化组织制定的一项脚本语言的标准化规范
岳泽以
2022/10/26
4840
JavaScript——ES6新增语法特性
前端成神之路-es6-ES6概念&新增语法&内置对象拓展
ES 的全称是 ECMAScript , 它是由 ECMA 国际标准化组织,制定的一项脚本语言的标准化规范。
海仔
2021/01/29
4880
ES6相关概念及新增语法
ES 的全称是 ECMAScript , 它是由 ECMA 国际标准化组织,制定的一项脚本语言的标准化规范。
星辰_大海
2020/10/27
4300
ES6相关概念及新增语法
「JS高级」ES6
请注意,本文编写于 2056 天前,最后修改于 169 天前,其中某些信息可能已经过时。
曼亚灿
2023/05/17
1.9K0
「JS高级」ES6
ES6归纳总结
let 的特点 let声明的变量只在所处的块级有效(块级作用域不受外部影响具有暂时死区特性),也就是说在{ }内声明的变量,只在 { }中可以使用,在其他地方不能使用。 防止循环变量,变成全局变量。 for(var i=0;i<3;i++){ } console.log(i);// 输出 3 for(let i=0;i<3;i++){ } console.log(i);/// 未定义 不存在变量提升 具有暂时死区 var num = 10; if (true){ console.log(num); //
用户4344670
2020/02/24
6850
前端架构师之01_ES6_基础
简单来说,ECMAScript是JavaScript语言的国际标准,JavaScript是实现ECMAScript标准的脚本语言。
张哥编程
2024/12/13
2180
箭头函数
箭头函数不绑定this关键字,箭头函数中的this,指向的是函数定义位置的上下文this
清出于兰
2020/10/26
1.4K0
中高级前端高频面试题分享
代码比较简单,我们只是在setTimeout的方法里面又调用了一次setTimeout,就可以达到间歇调用的目的。
前端迷
2019/05/28
9000
ES6相关概念与ES6新增语法
ES 的全称是 ECMAScript , 它是由 ECMA 国际标准化组织,制定的一项脚本语言的标准化规范。
梨涡浅笑
2020/10/28
4720
ES6相关概念与ES6新增语法
二、ES6新语法
图中可对比看出,如果用var声明,在循环外部还是可以使用i变量;但用let声明变量,循环外部不可以使用n变量
Dreamy.TZK
2020/07/03
4250
前端基础-JavaScript函数进阶
这种写法将一个匿名函数赋值给变量。这时,这个匿名函数又称函数表达式(Function Expression)
cwl_java
2020/03/26
5880
java8的stream流
在1.8新特性中有一个stream流 可以对集合进行很多操作,在开发里大量用到 先创建两个类,用于我们操作 import java.util.ArrayList; /** * @ClassName: StringList * @Date: 2020/6/21 0021 21:08 * @Description: 一个继承了ArrayList<String>的类 * @Author: <achao1441470436@gmail.com> */ public class StringList ex
阿超
2022/08/16
4210
mybatis常用条件查询总结(迭代一)
目录 1.mybatis中大于等于小于等于的写法 2.mybatis动态查询条件组装 3.mybatis批量条件 4.mybatis时间查询实现分页总结 1.mybatis中大于等于小于等于的写法 第一种写法(1): 原符号 < <= > >= & ' " 替换符号 < <= > >= & ' " 例如:sql如下: create_date_time >= #{s
挑战者
2018/06/29
2.8K0
JavaScript的箭头函数与普通函数区别?
箭头函数用更简洁的方式,来完成普通函数的功能,但是不具备普通函数拥有的属性: this 、 arguments 、 super 、 new.target,有两种表达形式:
Learn-anything.cn
2021/11/27
7310
es6新语法+vue2的学习笔记分享
shigen
2023/09/15
3230
es6新语法+vue2的学习笔记分享
VUE基础讲解
回调地狱:上一个接口还没有走完,下一个接口已经开始了,但是下一个接口需要上一个接口的数据
叶秋学长
2022/07/17
3810
VUE基础讲解
JS进阶系列02-JS面向对象的三大特征之封装
JS 作为面向对象的一门语言,拥有和其他面向对象语言一样的三大特征,即封装(encapsulation)、继承(inheritance )和多态(polymorphism )。关于继承的概念和实现,在本系列不在赘述,有兴趣的同学可以看看JS入门难点解析12-原型链与继承。
love丁酥酥
2018/08/27
8380
JS箭头函数之:为何用?怎么用?何时用?
在现代JS中最让人期待的特性就是关于箭头函数,用=>来标识。箭头函数有两个主要的优点:
Clearlove
2019/08/29
4.5K0
js遍历数组的几种方法
2、map:支持return,相当与原数组克隆了一份,把克隆的每项改变了,也不影响原数组
jamesjiang
2022/11/20
1.5K0
js遍历数组的几种方法
彩虹女神跃长空,Go语言进阶之Go语言高性能Web框架Iris项目实战-完善用户管理EP04
    书接上回,上一回我们完成了用户管理页面的构建,并且通过前端的Vue.js框架动态地获取表单数据,同时异步请求后端Iris接口进行入库操作,过程中使用函数封装可复用的逻辑。 本回我们将继续完善用户管理功能。
用户9127725
2022/09/23
6310
彩虹女神跃长空,Go语言进阶之Go语言高性能Web框架Iris项目实战-完善用户管理EP04
相关推荐
JavaScript——ES6新增语法特性
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档