日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

gin 项目结构_Go Web 框架 Gin 路由的学习

發布時間:2025/3/17 编程问答 45 豆豆
生活随笔 收集整理的這篇文章主要介紹了 gin 项目结构_Go Web 框架 Gin 路由的学习 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
Gin 是目前應用比較廣泛的Golang web 框架。目前,Github Star 數已經達到了3.8w. 框架的實現非常簡單,可定制性非常強,性能也比較好,深受golang開發者的喜愛。Gin 提供了web開發的一些基本功能。如路由,中間件,日志,參數獲取等,本文主要從源碼的角度分析Gin的路由實現。

Gin 的路由功能是基于 https://github.com/julienschmidt/httprouter 這個項目實現的。目前也有很多其他Web框架也基于該路由框架做了二次開發。

http 路由的接口

在 Gin 中,為了兼容不同路由的引擎,定義了 IRoutes 和 IRouter 接口,便于替換其他的路由實現。(目前默認是httprouter)

下面是一個路由的接口定義:

type?IRoutes?interface?{
???Use(...HandlerFunc)?IRoutes

??Handle(string,?string,?...HandlerFunc)?IRoutes
??Any(string,?...HandlerFunc)?IRoutes
??GET(string,?...HandlerFunc)?IRoutes
??POST(string,?...HandlerFunc)?IRoutes
??DELETE(string,?...HandlerFunc)?IRoutes
??PATCH(string,?...HandlerFunc)?IRoutes
??PUT(string,?...HandlerFunc)?IRoutes
??OPTIONS(string,?...HandlerFunc)?IRoutes
??HEAD(string,?...HandlerFunc)?IRoutes

??StaticFile(string,?string)?IRoutes
??Static(string,?string)?IRoutes
??StaticFS(string,?http.FileSystem)?IRoutes
}

type?HandlerFunc?func(*Context)

HandlerFunc 是一個方法類型的定義,我們定義的路由其實就是一個路徑與HandlerFunc 的映射關系。從上面的定義可以看出,IRoutes 主要定義了一些基于http方法、靜態方法的路徑和一組方法的映射。Use 方法是針對此路由的所有路徑映射一組方法,在使用上是為了給這些路由添加中間件。

除了上面的定義外,Gin 還有路由組的抽象。

type?IRouter?interface?{
??IRoutes
??Group(string,?...HandlerFunc)?*RouterGroup
}

路由組是在IRoutes 的基礎上,有了組的概念,組下面還可以掛在不同的組。組的概念可以很好的管理一組路由,路由組可以自己定義一套Handler方法(即一組中間件)。

個人認為IRouter的定義Group 應該返回 IRouter,這樣可以把路由組更加抽象,也不會改變現有服務的使用。期待看下Gin源碼什么時候會按照這種定義方法修改過來。

在Gin框架中,路由由 RouterGroup 實現。我們從構造和路由查找兩個方面分析路由的實現。

路由實現

路由的本質就是在給定 路徑與Handler映射關系 的前提下,當提供新的url時,給出對應func 的過程。其中可能需要從url中提取參數,或者按照 * 匹配 url 的情況。

首先,我們看下Gin中路由結構的定義。

//?gin?engine
type?Engine?struct?{
??RouterGroup
??//?...?其他字段
??trees????????????methodTrees
}

//?每個?http?方法定義一個森林
type?methodTrees?[]methodTree

type?methodTree?struct?{
??method?string
??root???*node
}

//?路由組的定義
type?RouterGroup?struct?{
??Handlers?HandlersChain
??basePath?string
??engine???*Engine
??root?????bool
}

從定義中可以看出,其實Gin 的 Engine 是復用了 RouterGroup。對于不同的 http method,都通過一個森林來存儲路由數據。下面是森林上每個節點的定義:

type?node?struct?{
??path??????string??//?當前路徑
??indices???string??//?對應children?的前綴
??wildChild?bool???//?可能是帶參數的,或者是?*?的,所以是野節點
??nType?????nodeType??//?參數節點,靜態節點
??priority??uint32??//?優先級?,優先級高的放在children 放在前面。
??children??[]*node??//?子節點
??handlers??HandlersChain?//?調用鏈
??fullPath??string??//?全路徑
}

從代碼實現上得知,這個森林其實是一個壓縮版本的Trie樹,每個節點會存儲前綴相同的路徑數據。下面,我們通過代碼來學習下路由的添加和刪除。

路由的添加

路由的添加,就是將path路徑添加到定義的Trie樹種,將handlers 添加到對應的node 節點。

func?(n?*node)?addRoute(path?string,?handlers?HandlersChain)?{
??//?初始化和維護優先級

??for?{
????//?查找前綴
????i?:=?longestCommonPrefix(path,?n.path)

?//?原有路徑長的情況下
?//?節點n?的?path?變為了公共前綴
?//?原有n?的path?路徑變為了現有n?的子節點

?//?當添加的path長的情況
?//?需要分情況討論:
?//?1.?如果是一個帶參數的路徑,校驗是否后續路徑不同,如果不同則繼續掃描下一段路徑
?//?2.?如果是帶?*?的路徑,?則直接報錯
?//?3.?如果已經有對應的首字母,修改當前node節點,并繼續掃描,并掃描下一段路徑
?//?4.?如果非參數或者?*?匹配的方法,則插入一個子節點路徑,并完成掃描

?//?最后注冊handlers,添加fullPath
????n.handlers?=?handlers
????n.fullPath?=?fullPath
????return
??}
}

從上面的代碼注釋可以看出,路由的添加,主要是通過不斷對比當前節點的path和添加的path,做添加節點或者節點變更的操作,達到添加path的目的。

路徑查找

在服務請求時,路由的責任就是給定一個url請求,拿到節點保存的handlers,以及url中包含的參數值。下面是對一個url 的解析實現。

type?nodeValue?struct?{
?handlers?HandlersChain
?params???*Params
?tsr??????bool
?fullPath?string
}

func?(n?*node)?getValue(path?string,?params?*Params,?unescape?bool)?(value?nodeValue)?{
walk:?//?Outer?loop?for?walking?the?tree
??for?{
????prefix?:=?n.path

//?如果比當前節點路徑要長:
//??-?非參數類型或模糊匹配的URL,如果和當前節點前綴匹配,直接查看?node?的子節點
//??-?參數化的node, 按照?/?分割提取參數,如果未結束,則繼續匹配剩下的路徑,否則返回結果。
//??-?*?匹配的node,將剩余的路徑添加到 param 中直接返回。
//?如果和當前節點相等,那就直接返回即可。
//?這里還做了非本方法的路徑匹配,用戶返回http 方法錯誤的異常報告。
??}
}

一個例子

下面通過一個例子,方便我們快速理解router的實現。

加入下面的一個路徑:

/search/?

/support/?

/blog/:post/?

/about-us/team/?

/contact/

在樹中,我們看到的樣子如下:

??Path
??\
??├s
??|├earch\
??|└upport\
??├blog\
??|????└:post
??|?????????└\
??├about-us\
??|????????└team\
??└contact\

在做路由查找時,通過路徑不斷匹配,找到對應的子節點。拿到對應子節點下的handler。完成路由的匹配。

總結

  • httprouter 沒有實現了routergroup功能,只是實現了router 的功能,在gin中做了實現
  • 通過Trie樹實現路由是比較基礎的一種實現方法,除了這種方法外,還可以考慮通過正則的方式提取路由。
  • Gin http 服務是基于 Go 的 net/http 庫的, net/http 庫中handler 的實現是針對不同的 http method 的,所以需要在engine 中針對不同的method 提供不同的trie 樹。
  • 在添加路由時,如果使用了 any 方法,則在每個http method 下都會添加一樣的路徑。
  • middleware 本質上只是一個 HandlerFunc.
  • 推薦閱讀

    • Gin 框架路由拆分與注冊


    喜歡本文的朋友,歡迎關注“Go語言中文網”:

    Go語言中文網啟用微信學習交流群,歡迎加微信:274768166,投稿亦歡迎

    總結

    以上是生活随笔為你收集整理的gin 项目结构_Go Web 框架 Gin 路由的学习的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。