go 1.22 增强 http.ServerMux 路由能力

之前

server

go 复制代码
func main() {
	http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
		fmt.Println("Received request:", r.URL.Path)
		fmt.Fprintf(w, "Hello, client! You requested: %s\n", r.URL.Path)
	})

	log.Println("Server is running on http://localhost:8080")
	if err := http.ListenAndServe(":8080", nil); err != nil {
		log.Fatal("ListenAndServe error: ", err)
	}
}

client

go 复制代码
func main() {
	url := "http://localhost:8080/some-path"

	// 创建HTTP GET请求
	resp, err := http.Get(url)
	if err != nil {
		log.Fatal("HTTP GET error: ", err)
	}
	defer resp.Body.Close()

	// 读取响应体
	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		log.Fatal("Error reading response body: ", err)
	}

	fmt.Println("Response from server:", string(body))
}

模式匹配优先级

如果两个模式重叠,那么更精确的模式优先。

如果 P1 符合 P2 请求的一个(严格)子集,P1 就比 P2 更精细

如果两者都不更具体,那么模式就会发生冲突

例外:

如果两个模式发生冲突,而其中一个有 HOST ,另一个没有,那么有 HOST 的模式优先。

example.com/ 比 / 更精细

因为第一个仅匹配主机 example.com 的请求,而第二个匹配任何请求

GET / 比 / 更精细

因为第一个仅匹配 GET 和 HEAD 请求,而第二个匹配任何请求

/b/{bucket}/o/default 比 /b/{bucket}/o/{noun} 更精细

第一个仅匹配第四个元素是文字 "default" 的路径,而在第二个中,第四个元素可以是任何内容

匹配方法

模式匹配将支持以 HTTP 方法开头,后跟空格,如 GET /demo 或 GET demo.com/

带有方法的模式仅用于匹配具有该方法的请求

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

go 复制代码
mux.HandleFunc("POST /demo/create", func(w http.ResponseWriter, r *http.Request) {
    fmt.Fprint(w, "demo create")
})

mux.HandleFunc("GET /demo/update", func(w http.ResponseWriter, r *http.Request) {
    fmt.Fprint(w, "demo update")
})

通配符

模式匹配将支持 {name} 或 {name...}

例如:/b/{bucket}/o/{objectname...}

该名称必须是有效的 Go 标识符和符合完整路径元素的标准

它们前面必须有斜杠,后面必须有斜杠或字符串末尾

例如:/b_{bucket} 不是有效的通配模式

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

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

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

示例

server

go 复制代码
func main() {
	http.HandleFunc("/demo/{id}", func(w http.ResponseWriter, r *http.Request) {
		id := r.PathValue("id")
		fmt.Fprintf(w, "id %s\n", id)
		fmt.Fprintf(w, "Hello, client! You requested: %s\n", r.URL.Path)
	})

	log.Println("Server is running  on /demo/x")
	if err := http.ListenAndServe(":8080", nil); err != nil {
		log.Fatal("ListenAndServe error: ", err)
	}
}

client

go 复制代码
func client() {
	url := "http://localhost:8080/demo/2?name=cucc"

	// 创建HTTP GET请求
	resp, err := http.Get(url)
	if err != nil {
		log.Fatal("HTTP GET error: ", err)
	}
	defer resp.Body.Close()

	// 读取响应体
	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		log.Fatal("Error reading response body: ", err)
	}

	fmt.Println("Response from server:\n", string(body))
}
相关推荐
Flash.kkl1 小时前
应用层协议HTTP
网络·网络协议·http
zs宝来了2 小时前
etcd Raft 实现:分布式一致性核心原理
golang·go·后端技术
呆萌很3 小时前
【GO】为任意类型添加方法练习题
golang
geovindu4 小时前
go: Simple Factory Pattern
开发语言·后端·设计模式·golang·简单工厂模式
亿牛云爬虫专家4 小时前
生产级Go高并发爬虫实战:突破 net_http 长连接与隧道代理IP切换陷阱
爬虫·http·golang·代理ip·keepalive·隧道代理·https connect
阿里加多5 小时前
第 5 章:Go 内存模型与 Happens-Before 原则
开发语言·后端·golang
止语Lab6 小时前
从一行超时配置到分布式可观测性——Go HTTP服务的渐进式演进实战
分布式·http·golang
上海云盾安全满满7 小时前
http与https有什么区别,https攻击要如何防护
网络协议·http·https
GDAL7 小时前
gin.Default() 深入全面讲解
golang·go·gin
hrhcode7 小时前
【java工程师快速上手go】三.Go Web开发(Gin框架)
java·spring boot·golang