gin 文档中的一个例子
func main() {
router := gin.Default()
// Simple group: v1
v1 := router.Group("/v1")
{
v1.POST("/login", loginEndpoint)
v1.POST("/submit", submi国外服务器tEndpoint)
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, 请大佬解惑, 谢谢)
我纯 Golang 路人。但是 Gin 用的 Router 是基于 httprouter 的,httprouter 用的是 Radix Tree 。所以一定有一步是把节点加入树里。你再看看源码吧。
router 就是 Engine 对象,源码里面你看不是有 engine: group.engine 吗?
https://github.com/xxjwxc/ginrpc
推荐这个
v1.POST() 和 v2.POST() 才是真正注册 route 的方法,group 只是方便理解和操作
那么 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 相关,如何快速查找匹配路由。
谢谢, 明白怎么回事了.