分组控制
原创Golang框架源码路由大约 2 分钟
分组控制
无论是简化路由的书写,还是方便鉴权等,基本所有的 Web 框架都有路由分组的设计
对象
将 分组 封装为一个结构体
- 需要一个存储这个分组的字段,我们就叫他前缀吧 pre
- 需要一个父级指针,实现分组再分组,和路径的拼接
- 需要一个中间件切片,用来实现过滤器、鉴权等
- 需要和Engine产生关联
type RGroup struct { pre string // 前缀 middlewares []HandleFunc // 中间件 parent *Group // 父节点 engine *Engine // 都挂在一个Engine上 }
Engine 也需要作出调整
- 为了期望的是 Engine 对象可以调用 Get 方法,RGroup对象也可以
- Engine是最顶层,RGroup 所有的方法Engine也都应该具备
- 所以,需要组合 RGroup
- 为了能在分组上应用中间件,在ServeHTTP方法中执行,需要再存储所有的分组信息
type Engine struct {
*RGroup
router *router
groups []*RGroup
} // 结构体
func New() *Engine {
engine := &Engine{router: newRouter()}
engine.RGroup = &RGroup{engine: engine}
engine.groups = []*RGroup{engine.RGroup}
return engine
}
这样就可以像Gin那样e.Group(pre)或者g.Group(pre)
func (g *RGroup) Group(pre string) *RGroup {
engine := g.engine
newGroup := &RGroup{
pre: g.pre + pre, // 拼接
parent: g,
engine: engine,
}
engine.groups = append(engine.groups, newGroup) // 添加到Engine维护的groups中
return newGroup
}
接下来就需要把咱们第一天写的路由中的方法再写一遍,绑定到 RGroup 对象上
type RGroup struct {
pre string // 前缀
middlewares []HandleFunc // 中间件
parent *RGroup // 父节点
engine *Engine // 都挂在一个Engine上
}
func (g *RGroup) addRoute(method string, pre string, handler HandleFunc) {
path := g.pre + pre
g.engine.router.addRoute(method, path, handler)
}
func (g *RGroup) Get(path string, handleFunc HandleFunc) {
g.addRoute("GET", path, handleFunc)
}
func (g *RGroup) Post(path string, handleFunc HandleFunc) {
g.addRoute("POST", path, handleFunc)
}
测试
func main() {
r := lee.New()
r.Get("/index", func(c *lee.Context) {
c.String(http.StatusOK, "<h1>Index Page</h1>")
})
v1 := r.Group("/v1")
{
v1.Get("/", func(c *lee.Context) {
c.String(http.StatusOK, "<h1>Hello lee</h1>")
})
v1.Get("/hello", func(c *lee.Context) {
// expect /hello?name=leektutu
c.String(http.StatusOK, "hello %s, you're at %s\n", c.Query("name"), c.Path)
})
}
v2 := r.Group("/v2")
{
v2.Get("/hello/:name", func(c *lee.Context) {
// expect /hello/leektutu
c.String(http.StatusOK, "hello %s, you're at %s\n", c.Param("name"), c.Path)
})
v2.Post("/login", func(c *lee.Context) {
c.JSON(http.StatusOK, lee.H{
"username": c.PostForm("username"),
"password": c.PostForm("password"),
})
})
}
r.Run(":8080")
}
优化项
- 路径名称没有
/可以自动加上
