negroni本身是一个中间件,不过它也提供了拓展,以帮助我们更简单地实现自己想要的功能的中间件。那么,我们究竟该如何实现中间件,才能能够封装到negroni中,从而通过negroni来调用呢?可以通过一个简单的例子分析:

package main
import (
"fmt"
"net/http"

"github.com/urfave/negroni"
"github.com/phyber/negroni-gzip/gzip"
)

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() //创建一个negroni
n.Use(gzip.Gzip(gzip.DefaultCompression))
n.UseHandler(mux)
n.Run(":3000")
}

我们从negroni创建之后开始分析。n.UseHandler(mux)函数:

n.UseHandler(mux)
    +func (n *Negroni) UseHandler(handler http.Handler)
        |n.Use(Wrap(handler))
        +func Wrap(handler http.Handler) Handler
            |return HandlerFunc(func(rw http.ResponseWriter, r *http.Request, next http.HandlerFunc)
        +func (n *Negroni) Use(handler Handler)
            |n.handlers = append(n.handlers, handler)
            |n.middleware = build(n.handlers)
            +func build(handlers []Handler) middleware
                |return middleware{handlers[0], &next}

调用n.UseHandler(mux)函数的过程中,同样也调用了n.Use()函数。说明negroni对于第三方中间件的使用是从n.UseHandler开始的。
  接下来,一起来分析追踪过程中遇到的函数:

1. UseHandler

该函数返回将handler传递给Wrap()函数

func (n *Negroni) UseHandler(handler http.Handler) {
    n.Use(Wrap(handler))
}

2. Wrap

该函数对handler进行封装,编程固定format的handler。

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)
    })
}

3. Use

该函数则将handler添加到Negroni结构体中。其中,midlleware是一个链表。

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)
}

+-----------------------------------------+
type Negroni struct {
    middleware middleware
    handlers   []Handler
}

type middleware struct {
    handler Handler
    next    *middleware
}

4. build

如果你了解C/C++,这个函数很好理解。它仅仅是一个迭代函数,实现了middleware链表的构建。

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}
}

5. 对ServerHTTP的处理

同时,我们也要清楚Handler是一个接口,一个Handler对象必须实现Handler接口。Handler接口定义如下:

type Handler interface {
    ServeHTTP(ResponseWriter, *Request)
}

negroni对ServeHTTP做了哪些处理呢?通过以下三个函数可以了解:

//函数类型,使用HandleFunc会调用
//func(rw http.ResponseWriter, r *http.Request, next http.HandlerFunc)的实现
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)
}

//实现ServerHTTP的封装
func (m middleware) ServeHTTP(rw http.ResponseWriter, r *http.Request) {
    m.handler.ServeHTTP(rw, r, m.next.ServeHTTP)
}

接下来,我们追踪n.Run(“:3000”)函数:

n.Run(":3000")
    +func (n *Negroni) Run(addr ...string)
    |finalAddr := detectAddress(addr...)
        +func detectAddress(addr ...string) string
    |l.Fatal(http.ListenAndServe(finalAddr, n))
        +func ListenAndServe(addr string, handler Handler) error
        |......

negroni.Run解析address后,最终调用了http.ListenAndServe来实现服务器。这一步,才最终完成了服务器的搭建;所有的handler都交付给了http.ListenAndServe去实现。

关于negroni对于第三方中间件的使用就分析到这里了。

转自:blog.csdn.net/Kiloveyousmile/article/details/78740242