Martini 極好的 Go WEB 框架

已知的其餘框架看到的是傳統OOP的影子, 處處充蝕 Class 風格的 OOP 方法. 而咱們知道GoLang中是沒有Class的. 筆者也曾努力用Go 的風格作WEB開發, 總感到力不從心. 寫出的代碼不能徹底稱之爲框架, 到更像一個拷貝源碼使用的應用. 要達到靈活須要修改源碼. 直到看到了 Martini. 純 GoLang 風格的框架出現了.git

核心Injector

InjectorMartini 的核心. 其代碼很是簡潔. 功能僅僅是經過反射包, 對函數進行參數類型自動匹配進行調用. 筆者曾經爲完成相似的功能寫了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 社區組件

開發者創建了 martini-contrib 組織. 這樣的管理方式更開放. 事實上這樣符合 Martini Injector 的風格, 組件之間的依賴能夠經過 Injector 的 Map/Invoke 機制完成.

相關文章
相關標籤/搜索