martini.go

对路由采用正则表达式处理,最终转化成正则表达式。

添加route对应的调用栈

go-martini 简单分析之二-LMLPHP

按照生成,验证,添加的步骤

route := newRoute(method, pattern, handlers)
route.Validate()
r.appendRoute(route)

martini会把任意类型的func 包装好,所以这里只要验证该类型是不是合适的func,因为一开始使用的是一个空的接口参数。

func validateHandler(handler Handler) {    if reflect.TypeOf(handler).Kind() != reflect.Func {        panic("martini handler must be a callable func")    }}

这里可以看下go的类型定义

const (
Invalid Kind = iota
Bool
Int
Int8
Int16
Int32
Int64
Uint
Uint8
Uint16
Uint32
Uint64
Uintptr
Float32
Float64
Complex64
Complex128
Array
Chan
Func
Interface
Map
Ptr
Slice
String
Struct
UnsafePointer
)

这里就加了个锁,安全的修改全局路由数组

func (r router) appendRoute(rt route) {
r.routesLock.Lock()
defer r.routesLock.Unlock()
r.routes = append(r.routes, rt)
}

我们要使用自己的handler,就需要将handler告诉go,这个其实也就是整个martini的真正起点。

func ListenAndServe(addr string, handler Handler) error {    server := &Server{Addr: addr, Handler: handler}    return server.ListenAndServe()}

这里我们传入m(martini):

logger.Fatalln(http.ListenAndServe(addr, m))

产生了较长的调用栈
go-martini 简单分析之二-LMLPHP

这里通过反射的方式去调用不同的handler

func (r *routeContext) run() {
for r.index < len(r.handlers) {
handler := r.handlers[r.index]
vals, err := r.Invoke(handler)
if err != nil {
panic(err)
}
r.index += 1
// if the handler returned something, write it to the http response
if len(vals) > 0 {
ev := r.Get(reflect.TypeOf(ReturnHandler(nil)))
handleReturn := ev.Interface().(ReturnHandler)
handleReturn(r, vals)
}
if r.Written() {
return
}
}
}

04-15 03:30