项目地址:https://geektutu.com/post/gee-day4.html
目标
这次要完成http的分组功能,简而言之,就是对于一些具有共同前缀的资源,我们可以通过哦Group()
来一起注册,且可以嵌入中间件,使得这些资源都有相同的特性。最终使用效果如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
|
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>Hello Gee</h1>")
})
v1.GET("/hello", func(c *gee.Context) {
// expect /hello?name=geektutu
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) {
// expect /hello/geektutu
c.String(http.StatusOK, "hello %s, you're at %s\n", c.Param("name"), c.Path)
})
v2.POST("/login", func(c *gee.Context) {
c.JSON(http.StatusOK, gee.H{
"username": c.PostForm("username"),
"password": c.PostForm("password"),
})
})
}
r.Run(":9999")
}
|
可以看得出来,这样实现会比较简洁漂亮。也可以使用嵌套和中间件。
实现
定义RouterGroup
类型,Engine
本身就是一个RouterGroup
,而所有的RouterGroup
都指向一个Engine
。
1
2
3
4
5
6
7
8
9
10
11
12
|
RouterGroup struct {
prefix string
middlewares []HandlerFunc // support middleware
parent *RouterGroup // support nesting
engine *Engine // all groups share a Engine instance
}
Engine struct {
*RouterGroup
router *router
groups []*RouterGroup // store all groups
}
|
留意Engine
在初始化时,Groups
只包含它自身的RouterGroup
。将原来为Engine
实现的GET
等方法,改为为RouterGroup
的,此时Engine
也可以隐性调用这些成员函数。这样就可以偷龙转凤一般,实现这种效果:
1
2
3
4
5
6
7
8
9
10
11
|
v1 := r.Group("/v1")
{
v1.GET("/", func(c *gee.Context) {
c.HTML(http.StatusOK, "<h1>Hello Gee</h1>")
})
v1.GET("/hello", func(c *gee.Context) {
// expect /hello?name=geektutu
c.String(http.StatusOK, "hello %s, you're at %s\n", c.Query("name"), c.Path)
})
}
|
说白了,现在就是加了个前缀功能而已。Grouping
真正的威力要在中间件中体现出来吧?