Go的Negroni库
来源:互联网 发布:joker game动漫 知乎 编辑:程序博客网 时间:2024/06/06 11:01
Go的Negroni库
Negroni库下载安装
go get -u github.com/urfave/negroni
Negroni库的结构
这是Negroni库的函数大致结构
首先由课上老师追踪Go的web服务包说起
(此追踪流程出自http://blog.csdn.net/pmlpml/article/details/78404838)
ListenAndServe(addr string, handler Handler) + server.ListenAndServe() | net.Listen("tcp", addr) + srv.Serve(tcpKeepAliveListener{ln.(*net.TCPListener)}) | srv.setupHTTP2_Serve() | baseCtx := context.Background() + for {} | l.Accept() | + select ... //为什么 | c := srv.newConn(rw) | c.setState(c.rwc, StateNew) // before Serve can return + go c.serve(ctx) // 新的链接 goroutine | ... // 构建 w , r | serverHandler{c.server}.ServeHTTP(w, w.req) | ... // after Serve
可以看到Go的http包在serverHandler{c.server}.ServeHTTP(w, w.req) 实现每个 conn 对应一个 serverHandler 的处理函数。
而在Negroni包中则只是实现了这一接口,该库可以认为是为了方便我们实现Handler.
那么首先我们从这个接口的实现开始,在http包中存在这么一个接口
type Handler interface { ServeHTTP(ResponseWriter, *Request)}
而在Negroni包中首先是该接口的实现
func (n *Negroni) ServeHTTP(rw http.ResponseWriter, r *http.Request) { n.middleware.ServeHTTP(NewResponseWriter(rw), r)}
可以看到Negroni类型将处理丢给了middleware处理,那么我们看看Negroni里的middleware以及其他成员
type Negroni struct { middleware middleware handlers []Handler}
可以看到有一个Handler的切片和一个middleware,对于这两者,其定义分别是
type middleware struct { handler Handler next *middleware}
这个定义就类似与c语言的链表结构了,可以将其理解为middleware是用来连接handler的数据结构吧
而对于Handler,其定义如下
// Handler handler is an interface that objects can implement to be registered to serve as middleware// in the Negroni middleware stack.// ServeHTTP should yield to the next middleware in the chain by invoking the next http.HandlerFunc// passed in.//// If the Handler writes to the ResponseWriter, the next http.HandlerFunc should not be invoked.type Handler interface { ServeHTTP(rw http.ResponseWriter, r *http.Request, next http.HandlerFunc)}
这里Handler将http接口稍微做了拓展,这是http.HandlerFunc的定义
// The HandlerFunc type is an adapter to allow the use of// ordinary functions as HTTP handlers. If f is a function// with the appropriate signature, HandlerFunc(f) is a// Handler that calls f.type HandlerFunc func(ResponseWriter, *Request)
可以看到本质上这与我们前面说到的http包调用的接口ServeHTTP是一个类型,Negroni包定义的Handler类型只是增加了一个指向http.HandlerFunc的参数,你可以在下文看到它会将所有handler形成链状结构
在Negroni包的Handler interface下面也有一段类似的HandlerFunc
// HandlerFunc is an adapter to allow the use of ordinary functions as Negroni handlers.// If f is a function with the appropriate signature, HandlerFunc(f) is a Handler object that calls f.type HandlerFunc func(rw http.ResponseWriter, r *http.Request, next http.HandlerFunc)
现在我们回过头看刚刚的n.middleware.ServeHTTP(NewResponseWriter(rw), r),这里我们跟踪一下middleware.ServeHTTP
func (m middleware) ServeHTTP(rw http.ResponseWriter, r *http.Request) { m.handler.ServeHTTP(rw, r, m.next.ServeHTTP)}
可以看到它调用了自己的成员handler的ServeHTTP,那么我们看一下对应函数
// HandlerFunc is an adapter to allow the use of ordinary functions as Negroni handlers.// If f is a function with the appropriate signature, HandlerFunc(f) is a Handler object that calls f.type HandlerFunc func(rw http.ResponseWriter, r *http.Request, next http.HandlerFunc)func (h HandlerFunc) ServeHTTP(rw http.ResponseWriter, r *http.Request, next http.HandlerFunc) { h(rw, r, next)}
可以看到它是将HandlerFunc进行执行,至此我们追踪完上面那个结构图的右边部分,那么HandlerFunc又是在哪里初始化或者传入Negroni中呢,我们先从github上给的start代码追踪一下
package mainimport ( "github.com/urfave/negroni" "net/http" "fmt")func main() { mux := http.NewServeMux() mux.HandleFunc("/", func(w http.ResponseWriter, req *http.Request) { fmt.Fprintf(w, "Welcome to the home page!") }) n := negroni.Classic() n.UseHandler(mux) n.Run(":3000")}
可以看到这里在UseHandler这里传入了HandleFunc(虽然类型和我们刚刚看到的Negroni定义的Handler不一样),我们尝试追踪一下UseHandler()
// UseHandler adds a http.Handler onto the middleware stack. Handlers are invoked in the order they are added to a Negroni.func (n *Negroni) UseHandler(handler http.Handler) { n.Use(Wrap(handler))}// UseHandlerFunc adds a http.HandlerFunc-style handler function onto the middleware stack.func (n *Negroni) UseHandlerFunc(handlerFunc func(rw http.ResponseWriter, r *http.Request)) { n.UseHandler(http.HandlerFunc(handlerFunc))}
这里我们可以看到两个差不多的函数(后面一个本质上是调用前一个实现相同功能),这里传入的是http包的Handler类型,我们看一下Wrap()函数
// Wrap converts a http.Handler into a negroni.Handler so it can be used as a Negroni// middleware. The next http.HandlerFunc is automatically called after the Handler// is executed.func Wrap(handler http.Handler) Handler { return HandlerFunc(func(rw http.ResponseWriter, r *http.Request, next http.HandlerFunc) { handler.ServeHTTP(rw, r) next(rw, r) })}// WrapFunc converts a http.HandlerFunc into a negroni.Handler so it can be used as a Negroni// middleware. The next http.HandlerFunc is automatically called after the Handler// is executed.func WrapFunc(handlerFunc http.HandlerFunc) Handler { return HandlerFunc(func(rw http.ResponseWriter, r *http.Request, next http.HandlerFunc) { handlerFunc(rw, r) next(rw, r) })}
可以看到这里Wrap()函数将http.Handler类型转为一个执行完本次handler然后执行next对应的handler的Negroni包的Handler类型
接着我们看一下UseHandler函数里面调用的Use函数
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)}
这里将传进来的handler加入handlers切片,然后调用build函数建立middleware,我们看一下build函数以及剩下的相关函数
func build(handlers []Handler) middleware { var next middleware if 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{}, }}
可以看到这是一个简单的递归过程,把handler拼成链表,然后建立middleware,至此我们可以看到Negroni库就是将你传进去的函数建成链表,然后由于Wrap()函数,默认会调用next(),也就是handler构成的链会一直调用到最后一个空的函数(即上示的voidMiddleware()返回的函数),当http包调用接口的时候,Negroni会执行middleware头指针(这只是类比)的handler然后一直往后面调用,这就是我们一开始给出的那张结构图了。
剩下的一些小细节
注意到刚刚的UseHandler等函数都是默认一直执行next的,那么有没有不执行next的呢,这里Negroni库提供了一个方法给你不调用next
func (n *Negroni) UseFunc(handlerFunc func(rw http.ResponseWriter, r *http.Request, next http.HandlerFunc)) { n.Use(HandlerFunc(handlerFunc))}
这里很显然就必须传入该包定义的Handler类型的函数作为参数。
剩下的还有Negroni的几个构造函数和Run之类的就不多讲,这里稍微看看就好
gofunc New(handlers ...Handler) *Negroni { return &Negroni{ handlers: handlers, middleware: build(handlers), }}
这是简单的New
然后这是类似与在尾部加上handler的构造函数
func (n *Negroni) With(handlers ...Handler) *Negroni { return New( append(n.handlers, handlers...)..., )}
然后是Classical,这里面的logger等都在该库另外的go文件实现了,这是Negroni内置的另外三个类型
func Classic() *Negroni { return New(NewRecovery(), NewLogger(), NewStatic(http.Dir("public")))}
- Go的Negroni库
- 浅析negroni-gzip 过滤器的源码
- negroni包和mux包的一点理解
- 简单阅读golang的net/http包和Negroni的源码
- golang学习之negroni对于第三方中间件的使用分析
- golang 使用negroni,实现server
- 【Go学习】Go的函数
- Negroni和Gorilla/mux 解析 Golang
- golang学习之negroni/gizp源码分析
- go第三方库的安装例子
- Go语言标准库Json的使用.
- Go学习笔记:flag库的使用
- Go学习笔记:xml库的使用
- C调用GO的动态链接库
- go下载被墙掉的第三方库
- Go?Go!(二) 初窥Go的特性
- Go?Go!(四) Go command的使用
- Go! Go! Go! 来我的另一个博客
- Qml滑动删除
- 第4章 最大子数组问题
- Chrome 控制台console的用法(学了之后对于调试js可是大大有用的哦
- mysql查询某个数据库中某个表的所有字段名、字段类型和注释
- 第四天:浪迹天涯网上商城(1.0版本)--后台管理系统--搭建图片服务器FTP
- Go的Negroni库
- python中锁机制
- Doolittle分解(matlab代码)
- 1020. 月饼 (25)
- 优秀的有趣的博客~值得一看
- nginx下布置ThinkPHP项目总结
- CodeForces
- Python 入门笔记一
- 5.4