专栏名称: GoCN
最具规模和生命力的 Go 开发者社区
目录
相关文章推荐
银行家杂志  ·  重磅会议部署!金融机构有新任务 ·  2 天前  
九章算法  ·  一年被裁两次,一个底层码农的大落大起 ·  2 天前  
九章算法  ·  Meta学神刷题奥义!《LeetCode通关 ... ·  4 天前  
中国人民银行  ·  中国人民银行、国家外汇局召开2025年全面从 ... ·  2 天前  
51好读  ›  专栏  ›  GoCN

Go语言版本1.22的路由增强功能

GoCN  · 公众号  ·  · 2024-02-14 23:27

正文

Go 1.22对 net / http 包中的路由器进行了两项增强:方式匹配和通配符。这些特性允许你将常见的路由表示为模式,而非Go代码。尽管这些功能简单易解释和使用,但想选择成功模式的正确规则(当多个模式匹配一个请求时)依然是个挑战。我们作出这些改变是为了持续让Go成为构建生产系统的优秀语言。我们研究了许多第三方web框架,提取出我们认为最常用的特性,并将它们集成进 net / http 。然后我们通过在GitHub上与社区进行讨论和问题建议,验证了我们的选择并改进了我们的设计。将这些特性添加到标准库意味着许多项目少了一个依赖性。但对于当前用户或带有高级路由需求的程序来说,第三方Web框架仍然是一个很好的选择。

新增功能

新的路由功能几乎完全影响到了 net / http . ServeMux 方法 Handle HandleFunc 传递的模式字符串,以及顶层函数 http . Handle http . HandleFunc 。唯一的API变化是在 net / http . Request 上添加了两个新方法,用于处理通配符匹配。我们将通过一个假设的博客服务器来说明这些变化,其中每篇帖子都有一个整数标识符。请求如GET /posts/ 234 取回ID为234的帖子。在Go 1.22之前,处理这些请求的代码将从这样的一行开始:

  1. http.Handle("/posts/", handlePost)

尾部的斜杠将所有以 /posts/ 开始的请求路由到 handlePost 函数,该函数将需要检查HTTP方法是否为GET,提取标识符,并取回帖子。由于方法检查并非严格必要以满足请求,忽略它将是一个自然的错误。这将意味着像 DELETE / posts / 234 这样的请求将取回帖子,这至少是令人惊讶的。而在Go 1.22中,现有代码将继续工作,或者你可以改写成这样:

  1. http.Handle("GET /posts/{id}", handlePost2)

这个模式匹配路径开始以 /posts/ 的请求并且有两个段的GET请求将匹配到这个模式(特别是,GET也可以匹配HEAD; 其他所有的方法都仅仅匹配一次)。 handlePost2 这个函数不再需要检查方法,并且可以通过在Request上使用新的 PathValue 方法来编写提取标识符字符串:

  1. idString := req.PathValue("id")

剩下的 handlePost2 将会行为类似 handlePost ,将字符串标识符转换为整数并获取帖子。如DELETE /posts/ 234 这样的请求在没有其他匹配模式被注册的情况下将失败。根据HTTP语法,一个 net / http 服务器将会回复这样的请求一个405 Method Not Allowed错误并在Allow头中列出可用的方法。一个通配符可以匹配一个全部的段,就像上面的例子中的 { id } ,或者,如果它以 ... 结束,它可以匹配路径中所有剩余的段,就像这个模式: /files/ { pathname ...} 。还有最后一点语法。正如我们上面展示的,以斜杠结尾的模式,像 /posts/ ,匹配所有以该字符串开始的路径。要只匹配结尾有斜杠的路径,你可以写成 /posts/ { $ } 。这将匹配到 /posts/ 但不会匹配到 / posts /posts/ { 234 } 。还有最后一点API: net / http . Request 有一个 SetPathValue 方法,以便标准库之外的路由器可以通过Request.PathValue使他们自己路径解析的结果可用。

优先级

每一个HTTP路由器必须处理重叠的模式,就像 /posts/ { id } /posts/ latest 。这两种模式都匹配“posts/latest”路径,但最多只能有一个处理请求。哪一个模式优先呢?一些路由器不允许重叠;其它的使用最后注册的模式。Go一直允许重叠,并且有选择更长的模式的优先级规则,不论注册顺序。保证顺序不依赖很重要并且必须向后兼容,但我们需要一个比“最长的赢”更好的规则。这个规则会选择 /post/ latest 而不是 /post/ { id } ,但却会选择 /posts/ { id }/{ category } 而不是 /posts/ { id







请到「今天看啥」查看全文