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))
}
相关推荐
jerry6094 小时前
7天用Go从零实现分布式缓存GeeCache(改进)(未完待续)
分布式·缓存·golang
杜杜的man5 小时前
【go从零单排】Closing Channels通道关闭、Range over Channels
开发语言·后端·golang
earthzhang20219 小时前
《深入浅出HTTPS》读书笔记(7):安全的密码学Hash算法
网络·网络协议·http·https·1024程序员节
甘橘籽10 小时前
【RPC】 gRPC、pb基本使用--经验与总结
golang
杜杜的man10 小时前
【go从零单排】HTTP客户端和服务端
开发语言·http·golang
AI原吾10 小时前
探索 Python HTTP 的瑞士军刀:Requests 库
开发语言·python·http·requests
找藉口是失败者的习惯10 小时前
探索 HTTP 请求方法:GET、POST、PUT、DELETE 等的用法详解
网络·网络协议·http
vortex510 小时前
HTTP 协议及内外网划分详解
网络·网络协议·http·网络安全
莫轻言舞10 小时前
Java Http 接口对接太繁琐?试试 UniHttp 框架吧
网络·网络协议·http
流氓也是种气质 _Cookie10 小时前
鸿蒙HarmonyOS 网络请求获取数据Http
http·鸿蒙·鸿蒙系统