Let's Go

  • 简介
    • Negroni 是一个框架吗?
    • 路由?
    • 基本功能
  • 源码阅读
    • Negroni Handler处理器
    • 如何构建中间件处理链
    • 中间件如何被调用
  • 参考资料

简介

在 Go 语言里,Negroni 是一个很地道的 Web 中间件,它是一个具备微型、非嵌入式、鼓励使用原生 net/http 库特征的中间件。

Negroni 是一个框架吗?

Negroni 不是一个框架,它是为了方便使用 net/http 而设计的一个库而已。

路由?

Negroni 没有带路由功能,使用 Negroni 时,需要找一个适合你的路由。不过好在 Go 社区里已经有相当多可用的路由,Negroni 更喜欢和那些完全支持 net/http 库的路由搭配使用,比如搭配 Gorilla Mux 路由器

基本功能

Negroni基本功能使用可以参考github详细说明

源码阅读

本质上来说Negroni是一个HTTP Handler,因为他实现了HTTP Handler接口,所以他可以被http.ListenAndServe使用,其次Negroni本身内部又有一套自己的Handler处理链,通过他们可以达到处理http请求的目的,这些Handler处理链中的处理器,就是一个个中间件。

Negroni Handler处理器

Negroni实现了HTTP的Handler,对于HTTP Request来说,就有一个统一的入口,所有的对HTTP Requet的处理,都会被Negroni通过ServeHTTP方法转交给Negroni内部注册的中间件。

func (n *Negroni) ServeHTTP(rw http.ResponseWriter, r *http.Request) {n.middleware.ServeHTTP(NewResponseWriter(rw), r)
}

Negroni自己定义的Handler处理器和HTTP Handler非常相似,唯一不同的是多了一个next参数,这个next参数是组成中间件处理链的核心。

type Handler interface {ServeHTTP(rw http.ResponseWriter, r *http.Request, next http.HandlerFunc)
}type HandlerFunc func(rw http.ResponseWriter, r *http.Request, next http.HandlerFunc)

如何构建中间件处理链

在调用Use方法的时候,会把Negroni的Handler存在自己的handlers字段中,这是一个Slice类型字段,可以保存我们存放的Negroni Handler。同时会基于这个存放Negroni Handler的Slice构建中间件处理链middleware

type Negroni struct {middleware middlewarehandlers   []Handler
}func (n *Negroni) Use(handler Handler) {if handler == nil {panic("handler cannot be nil")}n.handlers = append(n.handlers, handler)n.middleware = build(n.handlers)
}

middleware struct有两个字段,一个是当前的Negroni Handler,一个是指向下一个middleware的指针next。有了这样一个middleware struct,就可以构建一个完美的中间件处理链了。

type middleware struct {handler Handlernext    *middleware
}
func build(handlers []Handler) middleware {var next middlewareif len(handlers) == 0 {return voidMiddleware()} else if len(handlers) > 1 {next = build(handlers[1:])} else {next = voidMiddleware()}return middleware{handlers[0], &next}
}func voidMiddleware() middleware {return middleware{HandlerFunc(func(rw http.ResponseWriter, r *http.Request, next http.HandlerFunc) {}),&middleware{},}
}

当handlers参数为空的时候,直接通过voidMiddleware函数返回一个空的middleware。
当handlers参数只有1个处理器的时候,构建的milldeware就没有next了,所以next是通过voidMiddleware函数获得的,然后再通过return middleware{handlers[0], &next}组成生成的middleware并返回。

最后一种情况,就是有1个以上的Negroni Handler,那就通过build函数循环递归了,从第2个Handler开始,不停的往后递归处理,所以最先被添加的Negroni Handler会被放在中间件处理链的前面,也就意味着会被优先执行。

中间件如何被调用

调用了middleware.ServeHTTP方法,这就是中间件被执行的开始。middleware.ServeHTTP方法调用middleware中当前handler的ServeHTTP方法执行我们自己写的中间件处理逻辑。

func (m middleware) ServeHTTP(rw http.ResponseWriter, r *http.Request) {m.handler.ServeHTTP(rw, r, m.next.ServeHTTP)
}

当前的中间件被执行了,通过中间件函数中的next参数触发下一个中间件。我们在自己的中间件处理结束后,如果觉得有必要,就需要调用next函数,继续执行下一个中间件,如果我们不调用next函数,那么中间件链的处理,到这里就断了。

参考资料

Go语言经典库使用分析| Negroni 中间件

golang源代码阅读--Negroni相关推荐

  1. golang学习之negroni/gizp源码分析

    在 Go 语言里,Negroni 是一个很地道的 Web 中间件,它是一个具备微型.非嵌入式.鼓励使用原生 net/http 库特征的中间件.利用它地Use功能,我们可以很简单地自定义中间件并使用.其 ...

  2. XV6源代码阅读-中断与系统调用

    XV6源代码阅读-中断与系统调用 Exercise1 源代码阅读 1.启动部分: bootasm.S bootmain.c 和xv6初始化模块:main.c bootasm.S 由16位和32位汇编混 ...

  3. 非常好!!!Linux源代码阅读——环境准备【转】

    Linux源代码阅读--环境准备 转自:http://home.ustc.edu.cn/~boj/courses/linux_kernel/0_prepare.html 目录 Linux 系统环境准备 ...

  4. Tomcat源代码阅读系列之八:Tomcat 设计模式总结

    本篇我们将来分析一下Tomcat中所涉及到设计模式,本文我们将主要来分析 外观模式 , 观察者模式 , 责任链模式 , 模板方法模式 , 命令模式 . 在开始本文之前,笔者先说明一下对于设计模式的一点 ...

  5. Linux 源代码阅读知识点及要求

    说明:1.本次源代码阅读,以Linux 最新的稳定版本(2.6)为主: 2.源代码下载地址: 在官方站点 www.kernel.org 上最新稳定版本是 2.6.13.2: 在清华的 ftp 上随时都 ...

  6. 【转】Tomcat总体结构(Tomcat源代码阅读系列之二)

    本文是Tomcat源代码阅读系列的第二篇文章,我们在本系列的第一篇文章:在IntelliJ IDEA 和 Eclipse运行tomcat 7源代码一文中介绍了如何在intelliJ IDEA 和 Ec ...

  7. Linux 下源代码阅读工具 —— vim + TagList + CTags

    为什么不采用 Windows 下较为著名的源代码阅读软件 SourceInsight, 其一,其在 Linux 下的安装较为繁琐: 其二,切换代码时背景色的变化会为人的眼部产生极为不舒服的感觉: 其三 ...

  8. XV6源代码阅读-虚拟内存管理

    Exercise1 源代码阅读 内存管理部分: kalloc.c vm.c 以及相关其他文件代码 kalloc.c:char * kalloc(void)负责在需要的时候为用户空间.内核栈.页表页以及 ...

  9. ubuntu上安装源代码阅读工具Source-Navigator

    在ubuntu中,一款相对比较方便的源代码阅读编辑工具Source-Navigator . 1,下载 http://sourcenav.sourceforge.net/download.html 下载 ...

最新文章

  1. String.Format in javascript
  2. Robotium调用getActivity()导致程序挂起的方法
  3. linux下配置环境变量【原创】
  4. C语言 文件操作10--配置文件读写
  5. POJ 3264: Balanced Lineup
  6. Spring中@Resource与@Autowired、@Qualifier的用法与区别
  7. mysql 有empty_blob()_【原创】操作Blob类型的方法
  8. 【深度学习】深度学习分类与模型评估
  9. 恩智浦智能车摄像头循迹部分
  10. FS7022双节锂电池8.4V保护IC电路图
  11. 裸金属服务器性能描述,裸金属服务器性能描述
  12. Python常用字符编码
  13. c语言程序运行一会死机,为什么函数执行完了,还能导致系统死机?
  14. 如果要用运营的姿势,发支付宝红包
  15. 基于mschart控件,绘制工控采集类曲线,可对图像进行缩放,拖动滚动条显示放大后的图像
  16. 红领巾小创客机器人活动计划_红领巾小创客活动过程.docx
  17. 简单题-不用库函数,求解一个数字的平方根
  18. Win11:无法枚举容器中的对象 访问被拒绝
  19. 可以提高工作效率的应用工具,你知道几个呢
  20. cocos2d 使用SimpleAudioEngine加载音乐音效

热门文章

  1. 「小猪佩奇」:成功儿童IP背后的商业逻辑和方法论
  2. 递推法 c语言,递推法
  3. asp.net 大型商家联盟会员积分消费管理系统,带微信和文档【源码分享】
  4. 微信公众号文章如何排版?
  5. 全国计算机等级考试证书电子,全国计算机等级考试证书效力
  6. Advanced Auto Layout Toolbox
  7. 对复利计算器和股票投资的总结
  8. 解决页面favicon.ico文件不存在提示404问题
  9. js制作点击会自动隐藏的导航栏(固定在在头部的)
  10. STM32F103C8T6平衡车