Go1.22 新特性:终于增强 http.ServerMux 路由能力,将有更强的表现力!

大家好,我是煎鱼。

Go1.22 有一个比较重要的新特性,那就是基于提案《net/http: enhanced ServeMux routing》,增强了 http.ServerMux 的路由匹配能力。非常值得大家学习和关注。

本次的新特性主要是新增了 HTTP 方法和路径变量。

快速学习

在 Go 中,可以认为几乎所有的路由相关的库都会基于 net/http 或是兼容其 interface。否则容易脱离一个标准路线。

本文的主角 ServeMux,函数签名如下:

go 复制代码
type ServeMux
func NewServeMux() *ServeMux
func (mux *ServeMux) Handle(pattern string, handler Handler)
func (mux *ServeMux) HandleFunc(pattern string, handler func(ResponseWriter, *Request))
func (mux *ServeMux) Handler(r *Request) (h Handler, pattern string)
func (mux *ServeMux) ServeHTTP(w ResponseWriter, r *Request)

最简单的 Demo 如下:

go 复制代码
type apiHandler struct{}

func (apiHandler) ServeHTTP(http.ResponseWriter, *http.Request) {}

func main() {
	mux := http.NewServeMux()
	mux.Handle("/api/", apiHandler{})
	mux.HandleFunc("/", func(w http.ResponseWriter, req *http.Request) {
		...
		fmt.Fprintf(w, "你好,煎鱼!)
	})
}

用法非常的简单和标准,就是路径和实现方法。

新提案

缘由

这是一个很少见的提案,居然没有显著的说明没有这个的缺陷或问题。说明大家在潜意识里已经是比较认可的,不需要额外解释。

原因应该是:net/http.ServeMux 所提供的路由功能过于的基础了。

因此路由使用上,很多人都不优先推荐使用 net/http,而是更推荐 gorilla/mux 等知名开源库作为基础库,提高实现的效率和产能。

本次新提案将会增加:模式匹配、路径变量的支持。

Go1.22 路由增强

匹配方法

模式匹配将支持以 HTTP 方法开头,后跟空格,如 GET /eddycjy 或 GET eddycjy.com/ 中。 带有方法的模式仅用于匹配具有该方法的请求。

对照到代码中,也就是 Go1.22 起,http.ServeMux 可以这么写:

go 复制代码
mux.HandleFunc("POST /eddycjy/create", func(w http.ResponseWriter, r *http.Request) {
    fmt.Fprint(w, "脑子进煎鱼了!")
})

mux.HandleFunc("GET /eddycjy/update", func(w http.ResponseWriter, r *http.Request) {
    fmt.Fprint(w, "煎鱼进脑子了...")
})
...

通配符

模式匹配将支持 {name}{name...},例如:/b/{bucket}/o/{objectname...}

该名称必须是有效的 Go 标识符和符合完整路径元素的标准。它们前面必须有斜杠,后面必须有斜杠或字符串末尾。例如:/b_{bucket} 不是有效的通配模式。

Go1.22 起,http.ServeMux 可以这么写:

go 复制代码
mux.HandleFunc("/eddycjy/{id}", func(w http.ResponseWriter, r *http.Request) {
    id := r.PathValue("id")
    fmt.Fprintf(w, "id 值为 %s", id)
})

mux.HandleFunc("/eddycjy/{path...}", func(w http.ResponseWriter, r *http.Request) {
    path := r.PathValue("path")
    fmt.Fprintf(w, "path 值为 %s", path)
})
...

优先级

单一的优先规则:

  1. 如果两个模式重叠(有一些共同的请求),那么更具体的模式优先。
  2. 如果 P1 符合 P2 请求的一个(严格)子集,也就是说:如果 P2 符合 P1 的所有请求及更多请求,那么 P1 就比 P2 更具体。
  3. 如果两者都不更具体,那么模式就会发生冲突。
  4. 这条规则有一个例外:如果两个模式发生冲突,而其中一个有 HOST ,另一个没有,那么有 HOST 的模式优先。

以下是图示参考:

具体的例子:

  • example.com// 更具体,因为第一个仅匹配主机 example.com 的请求,而第二个匹配任何请求。
  • GET // 更具体,因为第一个仅匹配 GET 和 HEAD 请求,而第二个匹配任何请求。
  • /b/{bucket}/o/default/b/{bucket}/o/{noun} 更具体,因为第一个仅匹配第四个元素是文字 "default" 的路径,而在第二个中,第四个元素可以是任何内容。

总结

今天我们分享了 Go1.22 对于 net/http 标注库中的 ServerMux 路由相关功能的增强。

Go 还是有在吸收第三方开源库的一些不错的地方的,就是慢了一些。这都 10 多年了...

文章持续更新,可以微信搜【脑子进煎鱼了】阅读,本文 GitHub github.com/eddycjy/blo... 已收录,学习 Go 语言可以看 Go 学习地图和路线,欢迎 Star 催更。

推荐阅读

相关推荐
Joker-011110 小时前
牛客周赛Round 99(Go语言)
go·牛客周赛
Code季风16 小时前
Gin Web 层集成 Viper 配置文件和 Zap 日志文件指南(下)
前端·微服务·架构·go·gin
Code季风16 小时前
Gin Web 服务集成 Consul:从服务注册到服务发现实践指南(下)
java·前端·微服务·架构·go·gin·consul
struggleupwards17 小时前
golang中defer的小坑
后端·go
ん贤18 小时前
RESTful风格
后端·go·restful
风飘百里2 天前
分组加密核心原理与实践解析(AES/SM4)
go
岁忧2 天前
(LeetCode 每日一题) 1865. 找出和为指定值的下标对 (哈希表)
java·c++·算法·leetcode·go·散列表
Wo3Shi4七2 天前
哈希冲突
数据结构·算法·go
Code季风2 天前
GORM 部分关键字详解与关联查询实战:Preload 与 Association 的使用对比
go·orm