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)
    }
}
routers/r1.go
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)
    }
}
routers/r2.go

在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",
    })
}
handler.go

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)
    }
}
router.go

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",
    })
}
handler.go

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)
    }
}
router.go

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
}
routers/routers.go

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())
    }
}

~~~

posted on 2020-12-08 15:57  江湖乄夜雨  阅读(1594)  评论(0编辑  收藏  举报