社区微信群开通啦,扫一扫抢先加入社区官方微信群
社区微信群
go get -u github.com/urfave/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 main
import (
"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")))
}
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!