天天看點

gin源碼解讀2-揭開gin的神秘面紗

這段代碼的大概流程:

1.r := gin.Default()初始化了相關的參數 2./ping将路由及處理handler注冊到路由樹中 3.啟動服務

r.Run()其實調用的是err = http.ListenAndServe(address, engine), 結合上一篇文章可以看出來, gin其實利用了net/http的處理過程

上一篇文章有提到DefaultServeMux, 其實DefaultServeMux實作了ServeHTTP(ResponseWriter, *Request), 在request執行到server.go的serverHandler{c.server}.ServeHTTP(w, w.req)這一行的時候, 從DefaultServeMux取到了相關路由的處理handler.

是以, gin架構的Engine最重要的函數就是func (engine *Engine) ServeHTTP(w http.ResponseWriter, req *http.Request). Engine實作了Handler(server.go#L84-86), 讓net/http請求資料最終流回到gin中, 從gin的route tree中取到相關的中間件及handler, 來處理用戶端的request

在整個gin架構中最重要的一個struct就是Engine, 它包含路由, 中間件, 相關配置資訊等. Engine的代碼主要就在gin.go中

Engine中比較重要的幾個屬性, 其他的屬性暫時全部省略掉

Engine有幾個比較主要的函數:

New()主要幹的事情:

1.初始化了Engine 2.将RouterGroup的Handlers(數組)設定成nil, basePath設定成/ 3.為了使用友善, RouteGroup裡面也有一個Engine指針, 這裡将剛剛初始化的engine指派給了RouterGroup的engine指針 4.為了防止頻繁的context GC造成效率的降低, 在Engine裡使用了sync.Pool, 專門存儲gin的Context

Default()跟New()幾乎一模一樣, 就是調用了gin内置的Logger(), Recovery()中間件.

Use()就是gin的引入中間件的入口了. 仔細分析這個函數, 不難發現Use()其實是在給RouteGroup引入中間件的. 具體是如何讓中間件在RouteGroup上起到作用的, 等說到RouteGroup再具體說.

這兩句函數其實在這裡沒有任何用處. 我感覺這裡是給gin的測試代碼用的. 我們在使用gin的時候, 要想在404, 405添加處理過程, 可以通過NoRoute(), NoMethod()來處理.

這段代碼就是利用method, path, 将handlers注冊到engine的trees中. 注意這裡為什麼是HandlersChain呢, 可以簡單說一下, 就是将中間件和處理函數都注冊到method, path的tree中了.

<code>Run, RunTLS, RunUnix, RunFd 這些函數其實都是最終在調用net/http的http服務.</code>

這個函數相當重要了, 主要有這個函數的存在, 才能将請求轉到gin中, 使用gin的相關函數處理request請求.

利用request中的path, 從Engine的trees中擷取已經注冊的handler

在Next()執行handler的操作. 其實也就是下面的函數

如果在trees中沒有找到對應的路由, 則會執行serveError函數, 也就是404相關的.

參考連結