Go的Negroni库

来源:互联网 发布:joker game动漫 知乎 编辑:程序博客网 时间:2024/06/06 11:01

Go的Negroni库

Negroni库下载安装

go get -u github.com/urfave/negroni

Negroni库的结构

这是Negroni库的函数大致结构
Alt textNegroni结构
首先由课上老师追踪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")))}
原创粉丝点击