路由分组

91 阅读2分钟

对于路由分组,兔兔在这一章中,定义的路由分组结构体如下

RouterGroup struct {
    prefix      string
    middlewares []HandlerFunc // support middleware
    parent      *RouterGroup  // support nesting
    engine      *Engine       // all groups share a Engine instance
}

目前我们还没到中间件等AOP操作的实现,所以本文就没有将middlewares字段加上。就当前这个阶段,middlewares字段加上没什么用。

具体代码看Github

完整框架看Github

路由分组

关于路由分组的好处,我这就不细说了,对于这个功能,其实可以没有的,只是为了方便用户使用,我们额外加上这个功能

具体看下Gin框架的路由风分组如何使用的

package main

import "github.com/gin-gonic/gin"

func main() {
   r := gin.Default()
   r.Group("v1")
   {
      r.GET("/user", func(ctx *gin.Context) {})
      r.GET("/order", func(ctx *gin.Context) {})
   }
   // http://localhost:8080/v1/user
   // http://localhost:8080/v1/order
   r.Run(":8080")
}

我们想实现的效果

  1. engine能够能够调用Group方法实现分组
  2. GETPOSTPUTDELETE等衍生API转移到RouterGroup中实现
  3. addRouter方法转移到RouterGroup中实现,统一和路由树沟通

通过上述的分析,得出结论,RouterGroup结构体字段如下

type RouterGroup struct {
   prefix string       // 前缀
   parent *RouterGroup // 父路由组
   engine *Engine      // 对于这个属性,完全是为了从Engine中能够拿到路由树信息并注册和匹配路由
}

通过上述的分析,得出结论,Engine结构更新如下

type Engine struct {
   router       *router // 路由树
   *RouterGroup         // 路由组
}

完成效果1

func (group *RouterGroup) Group(prefix string) *RouterGroup {
   newGroup := &RouterGroup{
      prefix: fmt.Sprintf("%s%s", group.prefix, prefix),
      parent: group,
      engine: group.engine,
   }
   return newGroup
}

完成效果2

// GET 外部衍生API,提供给用户使用,现在嫁接到RouterGroup上
func (group *RouterGroup) GET(pattern string, handlerFunc HandlerFunc) {
   group.addRouter(http.MethodGet, pattern, handlerFunc)
}
func (group *RouterGroup) POST(pattern string, handlerFunc HandlerFunc) {
   group.addRouter(http.MethodPost, pattern, handlerFunc)
}
func (group *RouterGroup) DELETE(pattern string, handlerFunc HandlerFunc) {
   group.addRouter(http.MethodDelete, pattern, handlerFunc)
}
func (group *RouterGroup) PUT(pattern string, handlerFunc HandlerFunc) {
   group.addRouter(http.MethodPut, pattern, handlerFunc)
}

完成效果3

// 在路由组上定义一个添加路由的方法,这个作为唯一和路由树交互的入口
func (group *RouterGroup) addRouter(method string, pattern string, handlerFunc HandlerFunc) {
   pattern = fmt.Sprintf("%s%s", group.prefix, pattern)
   log.Printf("Add Router %4s - %s", method, pattern)
   group.engine.router.addRouter(method, pattern, handlerFunc)
}

上述完成测试

func main() {
    engine := neo.New()
    v1 := engine.Group("/v1")
    {
        v1.GET("/user", func(ctx *neo.Context) {
            ctx.String(http.StatusOK, "v1/user")
        })
        v1.POST("/order", func(ctx *neo.Context) {
            ctx.String(http.StatusOK, "v1/order")
        })
        v1.DELETE("/cart", func(ctx *neo.Context) {
            ctx.String(http.StatusOK, "v1/cart")
        })
        v1.PUT("/admin", func(ctx *neo.Context) {
            ctx.String(http.StatusOK, "v1/admin")
        })
    }
    v2 := engine.Group("/v2")
    {
        v2.GET("/user", func(ctx *neo.Context) {
            ctx.String(http.StatusOK, "v1/user")
        })
        v2.POST("/order", func(ctx *neo.Context) {
            ctx.String(http.StatusOK, "v1/order")
        })
        v2.DELETE("/cart", func(ctx *neo.Context) {
            ctx.String(http.StatusOK, "v1/cart")
        })
        v2.PUT("/admin", func(ctx *neo.Context) {
            ctx.String(http.StatusOK, "v1/admin")
        })
    }
    _ = engine.Run(":8080")
}