4. 路由分组

Kesa...大约 2 分钟golang

1. 路由分组

分组控制(Group Control)是 Web 框架应提供的基础功能之一。

若不进行路由分组,那么就需要针对每一个路由分别进行设置和操作。

对路由进行分组的好处:

  1. 统一管理同一组的路由
  2. 实现路由组嵌套,不同的子路由可以使用单独的中间件,也可以共享父路由的中间件

通过分组和中间件的组合,提高了系统的可扩展性。

2. 实现

https://github.com/dreamjz/golang-notes/tree/main/books/7-days-golang/Gee/day4-router-groupopen in new window

当前项目结构:

DAY4-ROUTER-GROUP
│  go.mod
│  go.work
│  main.go
│
└─gee
        context.go
        gee.go
        go.mod
        router.go
        router_group.go
        router_test.go
        trie.go

2.1 router_group

路由分组需要实现的功能:

  1. 添加子分组,通过当前分组创建子分组
  2. 注册路由,可以为当前分组注册路由

路由分组的数据结构如下:

type RouterGroup struct {
	prefix      string        // 路由组前缀
	middlewares []HandlerFunc // 中间件
	parent      *RouterGroup  // 父母分组
	engine      *Engine       // 所有分组持有同一个 Engine 实例
}
  • prefix:当前路由的前缀
  • middlewares:中间件函数列表
  • parent:父母分组,用于分组嵌套
  • engine:所有的分组持有同一个Engine实例,那么RouterGroup就具备Engine的所有功能,如注册路由

2.2 gee

所有的路由分组组成一个树形结构,所有的节点拥有一个指向其父母节点的指针。

Engine可以视作树的根节点,此时Engine与路由相关的功能就交给RouterGroup实现。

type Engine struct {
	*RouterGroup
	router *router
	groups []*RouterGroup // store all groups
}
  • groupsEngine实例存储所有的分组

2.3 router_group

package gee

import "log"

type RouterGroup struct {
	prefix      string        // 路由组前缀
	middlewares []HandlerFunc // 中间件
	parent      *RouterGroup  // 父母分组
	engine      *Engine       // 所有分组持有同一个 Engine 实例
}

// Group create a new RouterGroup
func (group *RouterGroup) Group(prefix string) *RouterGroup {
	engine := group.engine
	newGroup := &RouterGroup{
		prefix: group.prefix + prefix,
		parent: group,
		engine: engine, // All group share one Engine instance
	}
	// Add to group lists
	engine.groups = append(engine.groups, newGroup)
	return newGroup
}

func (group *RouterGroup) addRoute(method string, path string, handler HandlerFunc) {
	pattern := group.prefix + path
	log.Printf("Route %4s - %s", method, pattern)
	group.engine.router.addRoute(method, pattern, handler)
}

func (group *RouterGroup) GET(pattern string, handler HandlerFunc) {
	group.addRoute("GET", pattern, handler)
}

func (group *RouterGroup) POST(pattern string, handler HandlerFunc) {
	group.addRoute("POST", pattern, handler)
}

3. Demo

func main() {
	r := gee.New()

	r.GET("/index", func(c *gee.Context) {
		c.HTML(http.StatusOK, "<h1>Index Page</h1>")
	})

	v1 := r.Group("/v1")
	{
		v1.GET("/", func(c *gee.Context) {
			c.HTML(http.StatusOK, "<h1>Welcome v1</h1>")
		})

		v1.GET("/hello", func(c *gee.Context) {
			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 *gee.Context) {
			c.String(http.StatusOK, "Hello %s, you're at %s\n", c.Param("name"), c.Path)
		})

	}

	r.Run(":8000")
}
$ curl http://localhost:8000/v1/hello?name=alice
Hello alice, you're at /v1/hello

$ curl http://localhost:8000/v2/
404 NOT FOUND: /v2/

$ curl http://localhost:8000/v2/hello/alice
Hello alice, you're at /v2/hello/alice

Reference

  1. https://geektutu.com/post/gee-day4.htmlopen in new window
上次编辑于:
评论
  • 按正序
  • 按倒序
  • 按热度
Powered by Waline v2.15.2