本文主要针对Golang的内置库 net/http 做了简单的扩展,通过添加中间件的形式实现了管道(Pipeline)模式,这样的好处是各模块之间是低耦合的,符合单一职责原则,可以很灵活的通过中间件的形式添加一些功能到管道中,一次请求和响应在管道中的执行过程如下

首先, 我定义了三个测试的中间件 Middleware1,2,3 如下

func Middleware1(next http.Handler) http.Handler {

	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
fmt.Println("M1 in")
next.ServeHTTP(w, r)
fmt.Println("M1 out")
}) } func Middleware2(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
fmt.Println("M2 in")
next.ServeHTTP(w, r)
fmt.Println("M2 out")
}) } func Middleware3(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
fmt.Println("M3 in")
next.ServeHTTP(w, r)
fmt.Println("M3 out")
}) }

这里中间件的入参和出参的类型都是 http.Handler, 然后在 next.ServeHTTP() 的前后分别输出了 In 和 Out.

接下来,定义一个 Pipeline 的方法,里面使用嵌套的形式, 使用了上面定义的三个测试的中间件.

func Pipeline(next http.Handler) http.Handler {

	return Middleware1(Middleware2(Middleware3(next)))

}

然后还需要业务代码,这里我定义了 LoginHandler 和 RegisterHandler 两个方法

func LoginHandler(w http.ResponseWriter, r *http.Request) {

	fmt.Println("Login...")
w.Write([]byte("Login...")) } func RegisterHandler(w http.ResponseWriter, r *http.Request) { fmt.Println("Register...")
w.Write([]byte("Register...")) }

最后修改程序的 main 函数, 在 Login 接口上使用上面添加过中间件的 Pipeline

func main() {

	http.Handle("/Login", Pipeline(http.HandlerFunc(LoginHandler)))

	http.Handle("/Register", http.HandlerFunc(RegisterHandler))

	http.ListenAndServe(":8080", nil)

}

启动程序后,访问 http://localhost:8080/Login, 程序的输出如下,这和本文最上面的管道的流程图是一致的,然后访问 Register 接口, 控制台没有输出信息,当然也不会执行任何中间件。

现在已经实现了中间件的机制,但是,上面添加中间件是用嵌套的方法,这种方式不能说不太优雅,只能说非常的Low,接下来我们需要对管道进行优化

type Chain struct {
middlewares []func(handler http.Handler) http.Handler
} func Pipeline(next http.Handler) http.Handler { //return Middleware1(Middleware2(Middleware3(next))) return AddMiddlewares(Middleware1,Middleware2,Middleware3).Then(next) } func AddMiddlewares(m ...func(handlerFunc http.Handler) http.Handler) Chain { c := Chain{} c.middlewares = append(c.middlewares,m...) return c } func (c Chain) Then(next http.Handler) http.Handler { for i := range c.middlewares { prev := c.middlewares[len(c.middlewares)-1-i] next = prev(next)
} return next
}

首先定义了一个Chain 的struct,用来接收添加到管道中的中间件,在 AddMiddlewares() 函数中,接收了多个Handle, 然后组装到 Chain 对象并返回, 接下来调用 Then() 函数, 把管道中的中间件和业务的Handler 关联起来。在中间件的使用方式上, 这两种方法都是一样的,只需要调用 Pipeline() 方法就行了。

本文在go web中简单的实现了中间件的机制,这样带来的好处也是显而易见的,当然社区也有一些成熟的 middleware 组件,包括 Gin 一些Web框架中也包含了 middleware 相关的功能, 希望对您有用.

最后欢迎扫码关注公众号 【全球技术精选】

在 Golang 中实现一个简单的Http中间件的更多相关文章

  1. (一)在HTML页面中实现一个简单的Tab

    在HTML页面中实现一个简单的Tab 为了充分利用有限的HTML页面空间,经常会采用类似与TabControl的效果通过切换来显示更多的内容.本文将采用一种最为简单的方法来实现类似如Tab页切换的效果 ...

  2. golang gin框架中实现一个简单的不是特别精确的秒级限流器

    起因 看了两篇关于golang中限流器的帖子: Gin 开发实践:如何实现限流中间件 常用限流策略--漏桶与令牌桶介绍 我照着用,居然没效果-- 时间有限没有深究.这实在是一个很简单的功能,我的需求是 ...

  3. 在iOS中实现一个简单的画板App

    在这个随笔中,我们要为iPhone实现一个简单的画板App. 首先需要指出的是,这个demo中使用QuarzCore进行绘画,而不是OpenGL.这两个都可以实现类似的功能,区别是OpenGL更快,但 ...

  4. 在eclipse中配置一个简单的spring入门项目

    spring是一个很优秀的基于Java的轻量级开源框架,为了解决企业级应用的复杂性而创建的,spring不仅可用于服务器端开发,从简单性.可测试性和松耦合性的角度,任何java应用程序都可以利用这个思 ...

  5. 如何在Liferay 7中创建一个简单的JSF Portlet

    这个将在Liferay IDE 3.1 M3的发布版中提供创建的选项,但是你也可以通过命令行来创建. 1.这是Liferay JSF团队的官网:http://liferayfaces.org/ 你能在 ...

  6. 在 Visual Studio 中创建一个简单的 C# 控制台应用程序

    转载:https://blog.csdn.net/qq_43994242/article/details/87260824 快速入门:使用 Visual Studio 创建第一个 C# 控制台应用 h ...

  7. wpf中,一个简单的自定义treeview

    首先创建一个自定义控件,在里面定义好treeview的样式,将本来的三角形的图标变为加号的图标,并且添加节点之间的连线. <UserControl x:Class="TreeViewE ...

  8. 【Unity Shaders】Reflecting Your World —— 在Unity3D中创建一个简单的动态Cubemap系统

    本系列主要参考<Unity Shaders and Effects Cookbook>一书(感谢原书作者),同时会加上一点个人理解或拓展. 这里是本书所有的插图.这里是本书所需的代码和资源 ...

  9. Linux中实现一个简单的进度条【转】

    转自:http://blog.csdn.net/yuehailin/article/details/53999288 说起进度条,其实大家常常见到,比如说你在下载视频或文件的时候,提示你当前下载进度的 ...

随机推荐

  1. 瞎搞!你真的懂什么是ERP、中台和低代码吗?

    欢迎关注微信公众号:sap_gui (ERP咨询顾问之家) 互联网信息圈就是这样,写个不知所云的文章,再配上博眼球的标题,立马引来众多围观,不少公众号也蜂拥转载,完全不去思考文章写得对不对,有没有道理 ...

  2. 查找文件与cron计划任务

    查找文件 • 根据预设的条件递归查找对应的文件 find [目录] [条件1] [-a|-o] [条件2] ... -type  类型(f文件.d目录.l快捷方式) -name  "文档名称 ...

  3. centos 7 显示系统执行的进程

    命令:ps -aux ps -aux | more USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND root 1 0.0 0.2 1911 ...

  4. 惊呆了,Spring Boot居然这么耗内存!

    Spring Boot总体来说,搭建还是比较容易的,特别是Spring Cloud全家桶,简称亲民微服务,但在发展趋势中,容器化技术已经成熟,面对巨耗内存的Spring Boot,小公司表示用不起.如 ...

  5. 『无为则无心』Python基础 — 3、搭建Python开发环境

    目录 1.Python开发环境介绍 2.Python解释器的分类 3.下载Python解释器 4.安装Python解释器 5.Python解释器验证 1.Python开发环境介绍 所谓"工欲 ...

  6. NOIP模拟测试24「star way to hevaen·lost my music」

    star way to heaven 题解 大致尝试了一下并查集,记忆化搜索,最小生成树 最小生成树是正解,跑最小生成树然后找到最大的值 欧几里德距离最小生成树学习 prim楞跑 至于为什么跑最小生成 ...

  7. 带你掌握4种Python 排序算法

    摘要:在编程里,排序是一个重要算法,它可以帮助我们更快.更容易地定位数据.在这篇文章中,我们将使用排序算法分类器对我们的数组进行排序,了解它们是如何工作的. 本文分享自华为云社区<Python ...

  8. Fiber 树的构建

    我们先来看一个简单的 demo: import * as React from 'react'; import * as ReactDOM from 'react-dom'; class App ex ...

  9. centos7安装kubernetes1.18.5

    一.设置hosts 修改主机名 [root@localhost kubernetes]# hostnamectl set-hostname master69 四台服务器安装kebernetes,一个m ...

  10. 精尽Spring Boot源码分析 - 内嵌Tomcat容器的实现

    该系列文章是笔者在学习 Spring Boot 过程中总结下来的,里面涉及到相关源码,可能对读者不太友好,请结合我的源码注释 Spring Boot 源码分析 GitHub 地址 进行阅读 Sprin ...