Go 的路由规则较为简单,可以分为两种类型:以 /
结尾的 pattern
和不以 /
结尾的 pattern
。
/
的路由规则例如:
handle("/user", userhandler)
此时,客户端访问路径 uri
必须与 /user
完全匹配(如 https://*****/user
),路由才会匹配到 /user
定义的 handler
。
/
的路由规则例如:
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
可以通过以下方式实现:
handle("/user", userhandler)
handle("/user/", userhandler)
handle("/", userhandler)
/
的路由规则handle("/user/", userhandler)
表面上看,第一种和第三种方法似乎重复,但其中有细微区别,具体解析如下:
如果定义了:
handle("/", roothandler)
handle("/user/", userhandler)
此时,当访问 http://****/user
时,路由匹配不到 /user
定义的 handler
时,也不会进入 /
定义的路由规则。Go 服务器会返回一个 301 Moved Permanently
重定向,跳转到 /user/
。
简单来说,如果找不到 /user
对应的 handler
,Go 会自动尝试在 /user/
查找。如果找到了 /user/
的路由规则,Go 将返回一个重定向响应,指示客户端重定向到 /user/
。详细代码可参考 ServeMux
的 Handler
方法实现。
从性能角度来看,直接注册 handle("/user", userhandler)
,这样完全匹配 /user
的方式效率较高,它避免了额外的重定向开销。