HttpRouter 是用于Go的轻量级高性能 HTTP 请求路由器(也称为多路复用器或简称mux)。
与Go包的默认多路复用器net/http
相比,此路由器支持路由模式中的变量并匹配请求方法。它也可以更好地扩展。
该路由器针对高性能和小内存占用进行了优化。即使有很长的路径和大量的路线,它也能很好地扩展。压缩动态 trie(基数树)结构用于有效匹配。
特点:
仅显式匹配:对于其他路由器,例如http.ServeMux
,请求的 URL 路径可以匹配多个模式。因此他们有一些尴尬的模式优先规则,比如最长匹配或先注册,先匹配。通过这个路由器的设计,一个请求只能匹配一个或不匹配一个路由。结果,也没有意外的匹配,这使得它非常适合 SEO 并改善了用户体验。
**不必操心尾部斜线:**选择您喜欢的 URL 样式,如果缺少尾部斜线或有多余的斜线,路由器会自动重定向客户端。当然,只有在新路径有处理程序的情况下才会这样做。如果你不喜欢它,你可以关闭这个行为。
**路径自动更正:**除了检测丢失的或额外的斜杠,路由器还可以修复错误的情况并删除多余的路径元素(如../
或//
)。CAPTAIN CAPS LOCK是您的用户之一吗?HttpRouter 可以通过进行不区分大小写的查找并将他重定向到正确的 URL 来帮助他。
**路由模式中的参数:**停止解析请求的 URL 路径,只需为路径段命名,路由器将动态值传递给您。由于路由器的设计,路径参数非常便宜。
**零垃圾:**匹配和调度过程产生零字节的垃圾。唯一进行的堆分配是为路径参数构建键值对的切片,以及构建新的上下文和请求对象(后者仅在标准Handler
/ HandlerFunc
API 中)。在 3 参数 API 中,如果请求路径不包含参数,则不需要单个堆分配。
高性能: 基准不言自明。有关实施的技术细节,请参见下文。
**不再有服务器崩溃:**您可以设置Panic 处理程序来处理在处理 HTTP 请求期间发生的恐慌。然后路由器恢复并让PanicHandler
日志记录发生的事情并提供一个很好的错误页面。
**非常适合 API:**路由器设计鼓励构建合理的、分层的 RESTful API。此外,它还内置了对OPTIONS 请求和405 Method Not Allowed
回复的原生支持。
当然,您也可以设置自定义NotFound
和 MethodNotAllowed
处理程序并提供静态文件。
下载安装:
go get github.com/julienschmidt/httprouter
官方文档:
https://pkg.go.dev/github.com/julienschmidt/httprouter
package main
import (
"fmt"
"log"
"net/http"
"github.com/julienschmidt/httprouter"
)
func Index(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
fmt.Fprint(w, "Welcome!\n")
}
func Hello(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
fmt.Fprintf(w, "hello, %s!\n", ps.ByName("name"))
}
func main() {
router := httprouter.New()
router.GET("/", Index)
router.GET("/hello/:name", Hello)
log.Fatal(http.ListenAndServe(":8080", router))
}
在浏览器输入:http://127.0.0.1:8080/
,输出:Welcome!
在浏览器输入:http://127.0.0.1:8080/hello/Psych
,输出:hello, Psych!
在第一节中快速入门实战里:name
是一个命名参数。这些值可以通过 访问httprouter.Params
,它只是httprouter.Param
s 的一部分。您可以通过切片中的索引或使用ByName(name)
方法:name
获取参数的值:可以通过ByName("name")
.
命名参数仅匹配单个路径段:
Pattern: /user/:user
/user/gordon match
/user/you match
/user/gordon/profile no match
/user/ no match
**注意:**由于该路由器只有显式匹配,您不能为同一路径段注册静态路由和参数。例如,您不能同时注册模式/user/new
和/user/:user
相同的请求方法。不同请求方法的路由是相互独立的。
第二种类型是Catch-All参数,形式为*name
. 顾名思义,它们匹配一切。因此它们必须始终位于模式的末尾:
Pattern: /src/*filepath
/src/ match
/src/somefile.go match
/src/subdir/somefile.go match
HttpRouter 为所有的HTTP Method提供了快捷的使用方式,只需要调用对应方法即可
func (r *Router) GET(path string, handle Handle) {
r.Handle(http.MethodGet, path, handle)
}
func (r *Router) HEAD(path string, handle Handle) {
r.Handle(http.MethodHead, path, handle)
}
func (r *Router) OPTIONS(path string, handle Handle) {
r.Handle(http.MethodOptions, path, handle)
}
func (r *Router) POST(path string, handle Handle) {
r.Handle(http.MethodPost, path, handle)
}
func (r *Router) PUT(path string, handle Handle) {
r.Handle(http.MethodPut, path, handle)
}
func (r *Router) PATCH(path string, handle Handle) {
r.Handle(http.MethodPatch, path, handle)
}
func (r *Router) DELETE(path string, handle Handle) {
r.Handle(http.MethodDelete, path, handle)
}
如果 HttpRouter 对您来说有点过于简约,您可以尝试以下基于 HttpRouter 包构建的更高级的第 3 方 Web 框架之一: