gin框架路由拆分與註冊
轉自
gin框架路由拆分與註冊
基本的路由註冊
下面最基礎的gin路由註冊方式,適用於路由條目比較少的簡單專案或者專案demo。
package main import ( "net/http" "github.com/gin-gonic/gin" ) func helloHandler(c *gin.Context) { c.JSON(http.StatusOK, gin.H{ "message": "Hello q1mi!", }) } func main() { r := gin.Default() r.GET("/hello", helloHandler) if err := r.Run(); err != nil { fmt.Println("startup service failed, err:%v\n", err) } }
路由拆分成單獨檔案或包
當專案的規模增大後就不太適合繼續在專案的main.go
檔案中去實現路由註冊相關邏輯了,我們會傾向於把路由部分的程式碼都拆分出來,形成一個單獨的檔案或包:
我們在routers.go
檔案中定義並註冊路由資訊:
package main import ( "net/http" "github.com/gin-gonic/gin" ) func helloHandler(c *gin.Context) { c.JSON(http.StatusOK, gin.H{ "message": "Hello q1mi!", }) } func setupRouter() *gin.Engine { r := gin.Default() r.GET("/hello", helloHandler) return r }
此時main.go
中呼叫上面定義好的setupRouter
函式:
func main() { r := setupRouter() if err := r.Run(); err != nil { fmt.Println("startup service failed, err:%v\n", err) } }
此時的目錄結構:
gin_demo
├── go.mod
├── go.sum
├── main.go
└── routers.go
把路由部分的程式碼單獨拆分成包的話也是可以的,拆分後的目錄結構如下:
gin_demo ├── go.mod ├── go.sum ├── main.go └── routers └── routers.go
routers/routers.go
需要注意此時setupRouter
需要改成首字母大寫:
package routers import ( "net/http" "github.com/gin-gonic/gin" ) func helloHandler(c *gin.Context) { c.JSON(http.StatusOK, gin.H{ "message": "Hello q1mi!", }) } // SetupRouter 配置路由資訊 func SetupRouter() *gin.Engine { r := gin.Default() r.GET("/hello", helloHandler) return r }
main.go
檔案內容如下:
package main import ( "fmt" "gin_demo/routers" ) func main() { r := routers.SetupRouter() if err := r.Run(); err != nil { fmt.Println("startup service failed, err:%v\n", err) } }
路由拆分成多個檔案
當我們的業務規模繼續膨脹,單獨的一個routers
檔案或包已經滿足不了我們的需求了,
func SetupRouter() *gin.Engine { r := gin.Default() r.GET("/hello", helloHandler) r.GET("/xx1", xxHandler1) ... r.GET("/xx30", xxHandler30) return r }
因為我們把所有的路由註冊都寫在一個SetupRouter
函式中的話就會太複雜了。
我們可以分開定義多個路由檔案,例如:
gin_demo
├── go.mod
├── go.sum
├── main.go
└── routers
├── blog.go
└── shop.go
routers/shop.go
中新增一個LoadShop
的函式,將shop相關的路由註冊到指定的路由器:
func LoadShop(e *gin.Engine) { e.GET("/hello", helloHandler) e.GET("/goods", goodsHandler) e.GET("/checkout", checkoutHandler) ... }
routers/blog.go
中新增一個`LoadBlog的函式,將blog相關的路由註冊到指定的路由器:
func LoadBlog(e *gin.Engine) { e.GET("/post", postHandler) e.GET("/comment", commentHandler) ... }
在main函式中實現最終的註冊邏輯如下:
func main() { r := gin.Default() routers.LoadBlog(r) routers.LoadShop(r) if err := r.Run(); err != nil { fmt.Println("startup service failed, err:%v\n", err) } }
路由拆分到不同的APP
有時候專案規模實在太大,那麼我們就更傾向於把業務拆分的更詳細一些,例如把不同的業務程式碼拆分成不同的APP。
因此我們在專案目錄下單獨定義一個app
目錄,用來存放我們不同業務線的程式碼檔案,這樣就很容易進行橫向擴充套件。大致目錄結構如下:
gin_demo
├── app
│ ├── blog
│ │ ├── handler.go
│ │ └── router.go
│ └── shop
│ ├── handler.go
│ └── router.go
├── go.mod
├── go.sum
├── main.go
└── routers
└── routers.go
其中app/blog/router.go
用來定義post相關路由資訊,具體內容如下:
func Routers(e *gin.Engine) { e.GET("/post", postHandler) e.GET("/comment", commentHandler) }
app/shop/router.go
用來定義shop相關路由資訊,具體內容如下:
func Routers(e *gin.Engine) { e.GET("/goods", goodsHandler) e.GET("/checkout", checkoutHandler) }
routers/routers.go
中根據需要定義Include
函式用來註冊子app中定義的路由,Init
函式用來進行路由的初始化操作:
type Option func(*gin.Engine) var options = []Option{} // 註冊app的路由配置 func Include(opts ...Option) { options = append(options, opts...) } // 初始化 func Init() *gin.Engine { r := gin.New() for _, opt := range options { opt(r) } return r }
main.go
中按如下方式先註冊子app中的路由,然後再進行路由的初始化:
func main() { // 載入多個APP的路由配置 routers.Include(shop.Routers, blog.Routers) // 初始化路由 r := routers.Init() if err := r.Run(); err != nil { fmt.Println("startup service failed, err:%v\n", err) } }
總結
gin
框架是一個非常容易擴充套件的web框架,本文是我在日常編碼中總結的一點點經驗,因為世界上不可能有完全相同的專案,每個人也都有自己的程式設計習慣,關於gin框架路由註冊的方式我就在此拋磚引玉了。