## 引言
> 简单说下本章的重点
* 1、优化路由支持分组
* 2、编写单元测试、执行案例测试
* 3、[代码地址 https://github.com/18211167516/go-Ebb/tree/master/day4-routerGroup](https://github.com/18211167516/go-Ebb/tree/master/day4-routerGroup)
## 1、路由分组的概念
> 如果没有路由分组,我们需要针对每一个路由进行控制。但是真实的业务场景中,往往某一组路由需要相似的处理,大部分的分组是由前缀来区分的、并且可以支持分组的嵌套
## 2、定义路由分组
```golang
package ebb
type RouterGroup struct {
prefix string
middlewares []HandlerFunc // support middleware
parent *RouterGroup // support nesting
engine *Engine // all groups share a Engine instance
}
func (group *RouterGroup) Group(prefix string) *RouterGroup {
engine := group.engine
newGroup := &RouterGroup{
prefix: group.prefix + prefix,//支持分组嵌套
parent: group,
engine: engine,
}
engine.groups = append(engine.groups, newGroup)
return newGroup
}
func (group *RouterGroup) addRoute(method string, comp string, handler HandlerFunc) {
pattern := group.prefix + comp
group.engine.router.addRoute(method, pattern, handler)
}
// GET defines the method to add GET request
func (group *RouterGroup) GET(pattern string, handler HandlerFunc) {
group.addRoute("GET", pattern, handler)
}
// POST defines the method to add POST request
func (group *RouterGroup) POST(pattern string, handler HandlerFunc) {
group.addRoute("POST", pattern, handler)
}
```
## 2、优化engine结构
```golang
//核心结构体
type Engine struct{
*RouterGroup //v4新增 顶级路由组
router *router
groups []*RouterGroup // v4新增
}
//实例化结构体
func New() *Engine{
engine := &Engine{
router : newRouter(),
}
engine.RouterGroup = &RouterGroup{engine: engine}
engine.groups = []*RouterGroup{engine.RouterGroup}
return engine
}
```
## 3、单元测试
```golang
package ebb
import (
"testing"
"github.com/stretchr/testify/assert"
)
func TestRouteGroup(t *testing.T) {
r := New()
v2 := r.Group("/v2")
{
v2.GET("/hello/:name", func(c *Context) {
// expect /hello/ebbktutu
c.String(200, "hello %s, you're at %s\n", c.Param("name"), c.Path)
})
v2.POST("/login", func(c *Context) {
c.JSON(200, H{
"username": c.PostForm("username"),
"password": c.PostForm("password"),
})
})
}
n, params := r.router.getRoute("GET", "v2/hello/baibai")
if assert.NotNil(t, n,"404 not found ") {
assert.Equal(t,n.pattern,"/v2/hello/:name","should match /hello/:name")
assert.Equal(t,params["name"],"baibai","name should be equel to 'baibai'")
}
}
```
## 4、分组使用案例
```golang
package main
import (
"ebb"
)
func main(){
r := ebb.New()
r.GET("/index", func(c *ebb.Context) {
c.HTML(200, "<h1>Index Page</h1>")
})
v1 := r.Group("/v1")
{
v1.GET("/", func(c *ebb.Context) {
c.HTML(200, "<h1>Hello ebb</h1>")
})
v1.GET("/hello", func(c *ebb.Context) {
c.String(200, "hello %s, you're at %s\n", c.Query("name"), c.Path)
})
}
v2 := r.Group("/v2")
{
v2.GET("/hello/:name", func(c *ebb.Context) {
// expect /hello/ebbktutu
c.String(200, "hello %s, you're at %s\n", c.Param("name"), c.Path)
})
v2.POST("/login", func(c *ebb.Context) {
c.JSON(200, ebb.H{
"username": c.PostForm("username"),
"password": c.PostForm("password"),
})
})
}
r.Run(":8080")
}
```
## 5、本章节我们实现了路由分组(路由加前缀)
> 接下来到了重头戏,中间件的实现以及具体案例
有疑问加站长微信联系(非本文作者))