已知的其餘框架看到的是傳統OOP的影子, 處處充蝕 Class 風格的 OOP 方法. 而咱們知道GoLang中是沒有Class的. 筆者也曾努力用Go 的風格作WEB開發, 總感到力不從心. 寫出的代碼不能徹底稱之爲框架, 到更像一個拷貝源碼使用的應用. 要達到靈活須要修改源碼. 直到看到了 Martini. 純 GoLang 風格的框架出現了.git
Injector 是 Martini 的核心. 其代碼很是簡潔. 功能僅僅是經過反射包, 對函數進行參數類型自動匹配進行調用. 筆者曾經爲完成相似的功能寫了typeless, 這是一個繁瑣的高成本的實驗品. Injector 把事情簡單化了, Injector 假設函數的參數都具備不一樣的類型. 在WEB開發中的 HandlerFunc 一般都具備這樣的形式. 所以經過反射包能夠對參數進行自動的匹配並調用HandlerFunc, 固然事先要把全部可能使用到的參數 Map/MapTo 給 Injector 對象, 這很容易並且是能夠預見的.github
Martini的路由 router.go 寫的很是簡潔實用, 可見做者使用正則的功力很是深厚. 舉例:web
"/wap/:category/pow/**/:id"數據庫
匹配: "/wap/Golang/pow/Path1/ToPathN/Foo"app
這裏的中間件泛指應用需求中的流程控制, 預處理, 過濾器, 捕獲 panic, 日誌等等.這些依然是Injector在背後提供動力.框架
舉例源代碼中的 ClassicMartini ,固然你能夠按需求模仿一個.less
<!-- lang: cpp --> func Classic() *ClassicMartini { r := NewRouter() m := New() // m.Use(Logger()) // 啓用日誌 m.Use(Recovery()) // 捕獲 panic m.Use(Static("public")) // 靜態文件 m.Action(r.Handle) // 最後一個實際上是執行了默認的路由機制 return &ClassicMartini{m, r} }
其中 Recovery() 和 func (r *routeContext) run() 配合的方法很是值得讀一下, 一個簡單的計數器就完成了.函數
martini-contrib 中的 web 包展現瞭如何經過 Martini.Use 接口進行中間件的設計. 加入新的 HandlerFunc 參數類型就是經過 Map 完成的.ui
假如咱們要完成對 Response 流程的控制, 達不到某個條件中斷 Use 和 Action 設置的Handler. 那能夠簡單的經過 Use 加入本身的 Recovery 和判斷 Handler 實現debug
<!-- lang: cpp --> func Recovery() Handler { return func(res http.ResponseWriter, c Context, logger *log.Logger) { defer func() { if err := recover(); err != nil { s, ok := err.(string) // 示意用 string,你能夠定義類型 if ok && s == "dont ServerError" { return } res.WriteHeader(http.StatusInternalServerError) logger.Printf("PANIC: %s\n%s", err, debug.Stack()) } }() c.Next() } } func MyHandler() Handler { return func(req *http.Request) { if something { panic("dont ServerError") } } } m.Use(Recovery()) m.Use(MyHandler())
甚至
<!-- lang: cpp --> // 支持 Handlers 返回值輸出 m.Get("/", func() string { return "hello world" // HTTP 200 : "hello world" }) // 向 handlers 傳遞數據庫對象 db := &MyDatabase{} m := martini.Classic() m.Map(db) // the service will be available to all handlers as *MyDatabase // ... m.Run()
變化和自由度很是高. 正如 Martini 介紹的:
Martini is a powerful package for quickly writing modular web applications/services in Golang.
martini是一個極好的web框架,使人驚訝的簡單,不可思議的高效。
是的, 這纔是真正的 GoLang 風格.
開發者創建了 martini-contrib 組織. 這樣的管理方式更開放. 事實上這樣符合 Martini Injector 的風格, 組件之間的依賴能夠經過 Injector 的 Map/Invoke 機制完成.