gin框架概述
- 前面寫了兩篇從源代碼層面審視gin框架的文章,寫完以後感受結構比較亂。這裏再從新總結一下
- 做爲web框架,gin相對beego等更加輕量化,沒有orm等內容,gin實現了路由封裝,日誌,鑑權等功能。核心部分,是實現RESTful規範。將http method對應的path,找到相應的handler去處理請求,最終響應http請求。
gin框架的設計思路
- golang語言的一個重要特色就是擁有高質量的官方標準庫。設計web框架,天然也是離不開net/http包。下面是一個簡單的http server實現。
- 上邊這個例子,定義了一個struct,這個struct實現了http包的Handler接口,即ServeHTTP方法,那麼,就能夠把這個struct當成Handler傳給ListenAndServe。
- 其實,gin框架也是這個思路,定義了名爲Engine的struct,而後實現這個Engine實現了ServeHTTP方法,而後再將這個Engine做爲Handler傳給ListenAndServe就行。而後中間全部的路由管理,path對應的handler等,都由ServeHTTP去調用相應的實現函數。
啓動Engine
- Engine做爲核心的Handler,在gin框架中屬於核心位置,這裏貼出Engine的完整定義,重要字段的含義會在下文詳細闡述。這個定義很是明顯的特色就是定義了不少的bool類型的變量,很容易猜到這些bool值其實就是處理的flow的「路牌」
type Engine struct {
RouterGroup
RedirectTrailingSlash bool
RedirectFixedPath bool
HandleMethodNotAllowed bool
ForwardedByClientIP bool
AppEngine bool
UseRawPath bool
UnescapePathValues bool
MaxMultipartMemory int64
delims render.Delims
secureJsonPrefix string
HTMLRender render.HTMLRender
FuncMap template.FuncMap
allNoRoute HandlersChain
allNoMethod HandlersChain
noRoute HandlersChain
noMethod HandlersChain
pool sync.Pool
trees methodTrees
}
- 如何啓動Engine呢?有了上面的例子,具體如何啓動其實並不意外。
- 啓動以後,http請求天然就會交給Engine的ServeHTTP來處理。可是,咱們還不能立刻揭開ServeHTTP的面紗,咱們須要先了解gin是如何組織和管理http method, path和handler的。
gin管理method,path和handler
怎麼用gin
- 在弄清楚gin如何管理method,path和handler以前,先看看,gin通常都是怎麼用的。gin 例子。若是沒有gin的使用經驗,往下閱讀以前,務必瀏覽這個例子。
- gin.Default會生成一個Engine對象,再由這個對象去註冊相關的路由組,路由,method和handler。
路由管理——RouteGroup
-
上邊Engine結構第一個變量就是繼承了RouteGroup。之因此不定義新的變量,好比 rg RouteGroup來使用RouteGroup,是由於Engine須要直接使用RouteGroup實現的IRouter接口。git
type RouterGroup struct {
Handlers HandlersChain
basePath string
engine *Engine
root bool
}
- IRouter的Group函數的實現就是用做路由組管理。只要將正確的參數(string,HandlerFunc)傳給GET,POST等方法,就能夠將string對應的path,交給HandlerFunc來處理。(後邊會解釋HandlerFunc)
Handler是怎麼設計的
- 上邊的方法,HandlerFunc是重要的角色。那HandlerFunc是什麼呢?
- HandlerFunc是函數類型,函數的參數是Context對象。上邊連接裏的例子也能夠看出來,在使用gin框架時,業務邏輯的處理主要就是在本身定義的HandlerFunc裏邊。入參是*Context。這個Context又是啥?
- 從Context的代碼註釋,就能夠看出Context結構在gin框架中的重要性了。請求包含的數據,響應須要的數據,在Context裏邊都涵蓋了。
- 對比原生的http包,一個是須要實現ServeHTTP方法,一個是須要實現HandlerFunc函數。(method和function在編程裏邊是有區別的,千萬不要混爲一談)
管理http method
- 當用戶發起POST請求以後,是怎麼找到註冊的對應的POST方法的HandlerFunc的呢?這就要看IRouter接口的POST方法被調用的時候發生了什麼。
- 上邊的源碼能夠看出來,在整理path和handlers以後,會讓engine進行addRoute操做。
- 用樹結構存儲path,是一個很是天然的思路。除此以外,gin框架還生成了好幾棵樹,每棵樹對應一個http method。POST請求的話就回去POST樹上邊找對應的path和HandlerFunc。這個樹有專業名詞:基數樹!
總結
- gin框架會生成幾棵基數樹,分別對應http method。樹結構對應path的樹狀形態,每一個path會map到一個HandlerFunc。這樣,在接收到http請求的時候,先找到該請求對應的http method樹,再根據URL的path找到註冊好的HandlerFunc。HandlerFunc對應的業務邏輯須要gin的使用者藉助Context結構自行處理。
Engine的ServeHTTP
- 有了gin管理http method,path和HandlerFunc的基礎以後,咱們將目光轉回Engine的ServeHTTP方法當中來。
- 雖然上邊的代碼不難理解,可是這段代碼對gin的性能影響相當重要。關鍵的部分在於藉助sync.Pool對Context進行復用。
- 核心的處理邏輯最後交給handleHTTPRequest了。核心邏輯由源代碼翻譯過來就是:在接收到http請求的時候,先找到該請求對應的http method樹,再根據URL的path找到註冊好的HandlerFunc。HandlerFunc對應的業務邏輯須要gin的使用者藉助Context結構自行處理。