跳至主要內容

分组控制

程序员李某某原创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")
}

优化项

  • 路径名称没有/可以自动加上
上次编辑于:
贡献者: ext.liyuanhao3