go http库的路由规则


Go 的路由规则较为简单,可以分为两种类型:以 / 结尾的 pattern 和不以 / 结尾的 pattern

1. 不带 / 的路由规则

例如:

handle("/user", userhandler)

此时,客户端访问路径 uri 必须与 /user 完全匹配(如 https://*****/user),路由才会匹配到 /user 定义的 handler

2. 带 / 的路由规则

例如:

handle("/user/", userhandler)

客户端访问 https://*****/user/https://*****/user/**** 都会匹配到 /user/ 定义的 handler

实际上,即使客户端访问 https://*****/user,也可能匹配到 /user/ 对应的 handler,具体情况后续会解析。



示例

handle("/", roothandler)
handle("/user", userhandler)

在这种情况下:

  • 客户端访问 https://*****/user 时,路由会匹配到 /user 对应的 handler -> userhandler
  • 客户端访问 https://*****/user/ 时,路由会匹配到 / 对应的 handler -> roothandler
  • 同理,访问 https://*****/user/*** 时,路由仍会匹配到 / 对应的 handler -> roothandler

如何让 /user/user/**** 都匹配同一个 userhandler

可以通过以下方式实现:

1. 注册两个路由规则
handle("/user", userhandler)
handle("/user/", userhandler)
2. 使用根路由匹配所有路径
handle("/", userhandler)
3. 只注册带 / 的路由规则
handle("/user/", userhandler)

表面上看,第一种和第三种方法似乎重复,但其中有细微区别,具体解析如下:

如果定义了:

handle("/", roothandler)
handle("/user/", userhandler)

此时,当访问 http://****/user 时,路由匹配不到 /user 定义的 handler 时,也不会进入 / 定义的路由规则。Go 服务器会返回一个 301 Moved Permanently 重定向,跳转到 /user/

原因

简单来说,如果找不到 /user 对应的 handler,Go 会自动尝试在 /user/ 查找。如果找到了 /user/ 的路由规则,Go 将返回一个重定向响应,指示客户端重定向到 /user/。详细代码可参考 ServeMuxHandler 方法实现。

 

路由规则的效率

从性能角度来看,直接注册 handle("/user", userhandler),这样完全匹配 /user 的方式效率较高,它避免了额外的重定向开销。