gin 文档中的一个例子
func main() {
router := gin.Default()
// Simple group: v1
v1 := router.Group("/v1")
{
v1.POST("/login", loginEndpoint)
v1.POST("/submit", submitEndpoint)
v1.POST("/read", readEndpoint)
}
// Simple group: v2
v2 := router.Group("/v2")
{
v2.POST("/login", loginEndpoint)
v2.POST("/submit", submitEndpoint)
v2.POST("/read", readEndpoint)
}
router.Run(":8080")
}
router.Group
方法源码是这样的:
// Group creates a new router group. You should add all the routes that have common middlewares or the same path prefix.
// For example, all the routes that use a common middleware for authorization could be grouped.
func (group *RouterGroup) Group(relativePath string, handlers ...HandlerFunc) *RouterGroup {
return &RouterGroup{
Handlers: group.combineHandlers(handlers),
basePath: group.calculateAbsolutePath(relativePath),
engine: group.engine,
}
}
从上面的例子看, v1 := router.Group("/v1")
创建一个子分组v1
, 并且v1.engine
中存储了父级的信息, 这时候v1
知道它的父级是router
. 但是程序的入口是router
, 但好像并没有把v1
关联给router
, 那么router
怎么知道v1
的存在?
(初学 golang, 请大佬解惑, 谢谢)
1
abersheeran 2021-03-28 15:41:33 +08:00
我纯 Golang 路人。但是 Gin 用的 Router 是基于 httprouter 的,httprouter 用的是 Radix Tree 。所以一定有一步是把节点加入树里。你再看看源码吧。
|
2
676529483 2021-03-28 15:55:16 +08:00
router 就是 Engine 对象,源码里面你看不是有 engine: group.engine 吗?
|
3
BrjGmj70f6CLT51u 2021-03-28 15:56:41 +08:00
|
5
cyjme 2021-03-28 16:16:56 +08:00
那么 router 怎么知道 v1 的存在?
======= // Group creates a new router group. You should add all the routes that have common middlewares or the same path prefix. // For example, all the routes that use a common middleware for authorization could be grouped. func (group *RouterGroup) Group(relativePath string, handlers ...HandlerFunc) *RouterGroup { return &RouterGroup{ Handlers: group.combineHandlers(handlers), basePath: group.calculateAbsolutePath(relativePath), engine: group.engine, } } 源码中把 /v1 用于了 basePath 。 然后从 router.GET() 这个方法开始看,看什么时候用到 basePath (也就是 /v1 ) // GET is a shortcut for router.Handle("GET", path, handle). func (group *RouterGroup) GET(relativePath string, handlers ...HandlerFunc) IRoutes { return group.handle( http.MethodGet, relativePath, handlers) //进入 } func (group *RouterGroup) handle( httpMethod, relativePath string, handlers HandlersChain) IRoutes { absolutePath := group.calculateAbsolutePath(relativePath) //进入 handlers = group.combineHandlers(handlers) group.engine.addRoute( httpMethod, absolutePath, handlers) return group.returnObj() } func (group *RouterGroup) calculateAbsolutePath(relativePath string) string { return joinPaths(group.basePath, relativePath) //这里的 basePath 就是你的 "/v1",如果涉及到多重 group,可能是 /xxx/v1 } ================= 上面应该解答了你的疑问『怎么知道 v1 存在』,在每一次 GET/POST 执行的时候,都会根据之前的 basePath 进行计算。 继续深入,可以看 addRoute() ----> engine.trees 相关。然后就是 1 楼说的 httprouter tree 相关,如何快速查找匹配路由。 |