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))
}
相关推荐
YGGP1 小时前
浅析 Golang 内存管理
golang·内存泄露·内存逃逸
小白自救计划2 小时前
网络协议分析 实验七 FTP、HTTP、DHCP
网络·网络协议·http
Chandler242 小时前
Go 语言 net/http 包使用:HTTP 服务器、客户端与中间件
服务器·http·golang
z人间防沉迷k2 小时前
互联网协议的多路复用、Linux系统的I/O模式
linux·网络·http
z人间防沉迷k3 小时前
UDP和TCP协议
网络协议·tcp/ip·http·udp
Chandler243 小时前
Go语言:json 作用和语法
开发语言·golang·json
roman_日积跬步-终至千里4 小时前
【starrocks】StarRocks 常见 HTTP 操作与导入错误排查指南
starrocks·网络协议·http
Excuse_lighttime6 小时前
HTTP / HTTPS 协议
网络·网络协议·http·https
z人间防沉迷k6 小时前
TCP核心机制
网络·网络协议·tcp/ip·http
李匠20249 小时前
C++GO语言微服务之图片、短信验证码生成及存储
开发语言·c++·微服务·golang