gin项目的路由拆分与注册
参考博客
https://www.liwenzhou.com/posts/Go/gin_routes_registry/
基本的路由注册
func TestRouterGroup(t *testing.T){ // 定义默认引擎 r := gin.Default() // 路由组 userGroup userGroup := r.Group("/user") { // /user/index userGroup.GET("/index",func(c *gin.Context){ c.JSON(http.StatusOK,gin.H{ "msg":"user.index", }) }) // /user/login userGroup.GET("/login",func(c *gin.Context){ c.JSON(http.StatusOK,gin.H{ "msg":"user.login", }) }) } // 路由组 shopGroup shopGroup := r.Group("/shop") { // shop/index shopGroup.GET("/index",func(c *gin.Context){ c.JSON(http.StatusOK,gin.H{ "msg":"shop.index", }) }) // shop/login shopGroup.GET("/login",func(c *gin.Context){ c.JSON(http.StatusOK,gin.H{ "msg":"shop.login", }) }) } // 启动服务 r.Run("127.0.0.1:9900") }
将路由拆分成单独的包
当项目的规模增大后就不太适合继续在项目的main.go
文件中去实现路由注册相关逻辑了,我们会倾向于把路由部分的代码都拆分出来,形成一个单独的文件或包:
我们在routers.go
文件中定义并注册路由信息:
目录结构
在 routers/r1.go 中加入视图函数与生成引擎的代码:
package routers import ( "github.com/gin-gonic/gin" "net/http" ) // 视图函数 func helloHandler(c *gin.Context) { c.JSON(http.StatusOK, gin.H{ "status": "OK", "msg": "hello Handler!", }) } // 初始化路由的函数 注意首字母大写 func SetupRouter() *gin.Engine { // 默认引擎 r := gin.Default() // 注册路由 r.GET("/hello", helloHandler) return r }
在 main.go 中引入并启动服务即可:
package main import ( "fmt" "ginRouters/routers" ) func main() { router := routers.SetupRouter() if err := router.Run("127.0.0.1:9000"); err != nil{ fmt.Println("启动服务失败!err>>> ",err.Error()) } }
路由拆分成多个文件
当我们的业务规模继续膨胀,单独的一个routers
文件或包已经满足不了我们的需求了,
因为我们把所有的路由注册都写在一个SetupRouter
函数中的话就会太复杂了。
我们可以分开定义多个路由文件:
在 routers/r1.go 与 routers/r2.go 中分别写上加载路由的逻辑:(写成路由组的形式)
package routers import ( "github.com/gin-gonic/gin" "net/http" ) // r1的视图函数 func helloHandler(c *gin.Context) { c.JSON(http.StatusOK, gin.H{ "status": "OK", "msg": "hello Handler!", }) } func postHandler(c *gin.Context) { c.JSON(http.StatusOK, gin.H{ "status": "OK", "msg": "r1.postHandler", }) } // 添加一个load函数,将路由注册进去,这里可以放一个路由组 func LoadR1(e *gin.Engine) { r1Group := e.Group("/r1") { // 注册2条路由 r1Group.GET("/hello", helloHandler) r1Group.POST("/post", postHandler) } }
package routers import ( "github.com/gin-gonic/gin" "net/http" ) //r2的视图函数 func indexHandler(c *gin.Context){ c.JSON(http.StatusOK, gin.H{ "message":"r2.indexHandler", }) } func r2PostHandler(c *gin.Context){ c.JSON(http.StatusOK, gin.H{ "message":"r2.postHandler", }) } // load函数,将路由组注册进去 func LoadR2(e *gin.Engine) { r2Group := e.Group("/r2") { r2Group.GET("/index",indexHandler) r2Group.POST("/post",r2PostHandler) } }
在main.go中创建一个引擎,然后分别加载对应的路由即可:
package main import ( "fmt" "github.com/gin-gonic/gin" "ginRouters/routers" ) func main() { // 创建一个默认引擎 r := gin.Default() // 加载 r1 与 r2 的路由 routers.LoadR1(r) routers.LoadR2(r) // 启动服务 if err := r.Run("127.0.0.1:9003"); err != nil{ fmt.Println("服务启动失败!err: ",err.Error()) } }
路由拆分到不同的APP
有时候项目规模实在太大,那么我们就更倾向于把业务拆分的更详细一些,例如把不同的业务代码拆分成不同的APP。
因此我们在项目目录下单独定义一个app
目录,用来存放我们不同业务线的代码文件,这样就很容易进行横向扩展。
大致目录结构如下:
blog应用
视图函数写在app/blog/handler.go中:
package blog import ( "github.com/gin-gonic/gin" "net/http" ) // blog的视图函数 func postHandler(c *gin.Context){ c.JSON(http.StatusOK,gin.H{ "msg":"blog.postHandler", }) } func commentHandler(c *gin.Context){ c.JSON(http.StatusOK, gin.H{ "msg":"blog.commentHandler", }) }
router.go中注册路由组:
package blog import "github.com/gin-gonic/gin" // load blog的路由 写成路由组 func LoadBlogRouters(e *gin.Engine) { blogGroup := e.Group("/blog") { blogGroup.POST("/post", postHandler) blogGroup.POST("/comment", commentHandler) } }
shop应用
视图函数写在handler.go中:
package shop import ( "github.com/gin-gonic/gin" "net/http" ) // shop的视图函数 func goodsHandler(c *gin.Context){ c.JSON(http.StatusOK,gin.H{ "msg":"shop.goods", }) } func checkHandler(c *gin.Context){ c.JSON(http.StatusOK,gin.H{ "msg":"shop.check", }) }
router.go中注册路由组:
package shop import "github.com/gin-gonic/gin" // load shop中的路由 写成路由组 func LoadShopRouters(e *gin.Engine){ shopGroup := e.Group("/shop") { shopGroup.POST("/goods", goodsHandler) shopGroup.POST("/check", checkHandler) } }
routers/routers.go中初始化所有应用的路由
routers/routers.go
中根据需要定义Include
函数用来注册子app中定义的路由,InitRouters
函数用来进行路由的初始化操作:
package routers import ( "github.com/gin-gonic/gin" ) type Option func(engine *gin.Engine) var options []Option // 注册app的路由配置 func Include(optObjs ...Option) { // 打散传参 options = append(options, optObjs...) } // Init函数用来进行路由的初始化 func InitRouters() *gin.Engine{ // 默认引擎 r := gin.Default() for _, opt := range options{ // 注册路由 opt(r) } return r }
main.go
main.go
中按如下方式先注册子app中的路由,然后再进行路由的初始化:
package main import ( "fmt" "ginRouters/routers" "ginRouters/app/blog" "ginRouters/app/shop" ) func main() { // 加载多个APP的路由配置 // 将对应的load方法传进去 routers.Include(shop.LoadShopRouters, blog.LoadBlogRouters) // 初始化路由 r := routers.InitRouters() // 启动服务 if err := r.Run("127.0.0.1:9004"); err != nil{ fmt.Println("err>>> ", err.Error()) } }
~~~