一些路由管理混亂的例子

首先,我先給大家看一個曾經維護過的項目的路由文件 router.go, 這個項目用的也是Gin框架,整個文件里500多行全是API接口的路由。

你說這么寫不好維護吧,全項目的路由都在這里不用其他地方找,按能用就行的標準,確實是能用。

而且Gin的官方文檔里在路由這塊的例子確實也是這么寫的。

// Gin 官方文檔示例
func main() {
router := gin.Default()

// 簡單的路由組: v1
v1 := router.Group("/v1")
{
v1.POST("/login", loginEndpoint)
v1.POST("/submit", submitEndpoint)
v1.POST("/read", readEndpoint)
}

// 簡單的路由組: v2
v2 := router.Group("/v2")
{
v2.POST("/login", loginEndpoint)
v2.POST("/submit", submitEndpoint)
v2.POST("/read", readEndpoint)
}

router.Run(":8080")
}

隨著項目開發的迭代,我們寫的接口往往會越來越多,如果還按上面這樣把API的路由寫到一個文件里,那么整個路由文件就會變得像上面那個例子一樣,變得又亂又長。

今天介紹兩個步驟讓我們能把項目路由分模塊管理起來。本節內容節選自我的專欄《Go項目搭建和整潔開發實戰》

項目中怎么規劃和管理路由

首先根據我們上一節 「Go 項目怎么做好分層架構和目錄規劃」中設計的項目目錄結構,在API處理器對應的api目錄下的controler和router子目錄中分別存放每個模塊對應的Api handler 和 router 文件。

舉例來說,假設我們項目中想在有用戶和訂單兩個模塊,那么此時項目的api/controller 和 api/router 中應該分別有倆個文件與業務模塊對應。

.
|---api # API 處理器模塊
| |---controller # 控制器
| | |---order.go # 訂單模塊的 Api Handler
| | |---user.go # 用戶模塊的 Api Handler
| |---router # 路由
| | |---order.go # 訂單模塊的路由文件
| | |---router.go # 負責路由初始化和注冊各模塊路由的總文件
| | |---user.go # 用戶模塊的路由文件

在路由目錄中 router.go 負責路由初始化和注冊各模塊路由的總文件,此外一些要全局應用的中間件也會在這里設置,比如像下面這樣。

而進入到每個模塊的路由文件中,首先其路由組設置的路由前綴要跟模塊名保持統一,另外還可以根據該模塊中接口的統一特征在路由組上應用中間件。

比如是訂單模塊的接口,那么路由組的前綴可以設置成”/order/”這樣所有訂單相關的接口都在這個路徑下,因為用戶只能看自己的訂單,所以所有訂單相關的接口都需要用戶認證后才能訪問。我們可以在路由組上應用用戶認證中間件,為組內的所有接口增加這項限制,比如像下面這樣。

最后多提一點,如果業務模塊里的接口太多,像controller/order.go 這樣,單個文件不好組織整個模塊的API handler的時候也可以把其升級為目錄,變成下面這種結構。

.
|---api # API 處理器模塊
| |---controller # 控制器
| | |---order # 訂單模塊的 Api Handler
| | | |---xxx.go
| | | |---yyy.go
| |---router # 路由
......

好了,介紹完Web項目管理路由的大概思路后,我帶大家一起看下,怎么用這個思路在Gin項目中分模塊管理

用Gin實現路由的分模塊管理

分模塊首先就是按照URI的目錄或者叫路由組進行管理,首先我們在項目的 api/router 目錄下定義一個router.go文件,它負責路由初始化和注冊各模塊的路由。

在其中增加如下代碼:

func RegisterRoutes(engine *gin.Engine) {
// use global middlewares
engine.Use(middleware.StartTrace(), middleware.LogAccess(), middleware.GinPanicRecovery())
routeGroup := engine.Group("")
registerBuildingRoutes(routeGroup)
}

在這里我們先把所有全局中間件應用上,Gin框架的路由組是靠 gin.Group 來維護的,我們先在全局的router方法中通過 engine.Group(“”) 拿到一個不帶任何路由前綴的 gin.Group 作為頂級路由組。

之后再把它傳遞給每個子模塊的路由注冊方法,在這個頂級路由組的基礎上再去生成各個路由模塊的路由組對象,用來注冊它們各自的路由。

我們先把之前搭建框架時寫的那些測試方法的路由都放在api/router/building.go 文件中,所有路由都以”/building/”作為前綴。

// 存放一些項目搭建過程中驗證效果用的接口的路由

func registerBuildingRoutes(rg *gin.RouterGroup) {
// 這個路由組中的路由都以 /building 開頭
g := rg.Group("/building/")
// 測試 Ping
g.GET("ping", controller.TestPing)
// 測試日志文件的讀取
g.GET("config-read", controller.TestConfigRead)
// 測試日志門面Logger的使用
g.GET("logger-test", controller.TestLogger)
// 測試服務的訪問日志
g.POST("access-log-test", controller.TestAccessLog)
// 測試服務的崩潰日志
g.GET("panic-log-test", controller.TestPanicLog)
// 測試項目自定義的AppError 打印錯誤鏈條和錯誤發生位置
g.GET("customized-error-test", controller.TestAppError)
// 測試統一響應--返回對象數據
g.GET("response-obj", controller.TestResponseObj)
// 測試統一響應--返回列表和分頁
g.GET("response-list", controller.TestResponseList)
// 測試統一響應--返回錯誤
g.GET("response-error", controller.TestResponseError)
}

相應的路由對應的API Handler也需要從main.go 中挪到 controller 包中, 我們在api/controller中新建building.go 用來存放搭建框架過程中編寫的那些測試接口的Handler方法。

把已有的Controller挪到對應的文件后,可以隨機抽查幾個看看看到這些接口是否都還能正常訪問,接下來再觀察下我們請求接口時產生的應用日志。

應用日志仍然是能正常的把請求的訪問日志和錯誤響應日志都給記錄下來,證明代碼改動沒問題。

路由分模塊管理的規則

上面我演示了為了做路由分模塊管理在項目中做的那些基礎工作,未來進入需求開發階段我們只要按照這個規則分模塊去管理路由就行啦。

后面我們在項目開發時,API的路由管理也遵循這個原則:

如果按照我們上節課「Go 項目怎么做好分層架構和目錄規劃」中介紹的使用應用服務和領域服務拆分邏輯的方式。控制器層應該每個Controller 方法的代碼都很少,Controller中的代碼不會太臃腫,除非某個模塊下接口數量特別多才需要多個controller文件來存放模塊下的Controller代碼。

本文章轉載微信公眾號@網管叨bi叨

上一篇:

深入解密Elasticsearch查詢優化:巧用Profile工具/API提升性能

下一篇:

沒想到一個 HTTP Client 居然考慮這么多場景
#你可能也喜歡這些API文章!

我們有何不同?

API服務商零注冊

多API并行試用

數據驅動選型,提升決策效率

查看全部API→
??

熱門場景實測,選對API

#AI文本生成大模型API

對比大模型API的內容創意新穎性、情感共鳴力、商業轉化潛力

25個渠道
一鍵對比試用API 限時免費

#AI深度推理大模型API

對比大模型API的邏輯推理準確性、分析深度、可視化建議合理性

10個渠道
一鍵對比試用API 限時免費