Go 1.22新路由功能的问题讨论

Go 1.22新路由功能的问题讨论 Go 1.22.0 版本为 HTTP 路由器引入了 REST 风格的路由功能。根据这篇博客文章,它应该支持路由增强:Go 1.22 的路由增强功能 - Go 编程语言

例如

http.Handle(“GET /posts/{id}”, handlePost2)

将允许你这样做

idString := req.PathValue(“id”)

我正在使用以下 Go 程序:

package main

import (
	"fmt"
	"log"
	"net/http"
)

func main() {
	http.HandleFunc("GET /articles/{id}", articles)

	log.Fatalln(http.ListenAndServe(":8080", nil))
}

func articles(w http.ResponseWriter, r *http.Request) {
	fmt.Fprintln(w, "hello")
}

然而,当我使用这个 curl 命令时

curl -X GET localhost:8080/articles/11

我得到了一个 404 页面未找到的错误

我正在使用最新的 Go 版本:

go version go version go1.22.0 linux/amd64

我使用 “go run” 命令运行该程序

我期望我的处理程序能根据这个路由来处理此请求。为什么会这样?


5 回复

升级到 Go 1.22 时请检查你的 go.mod 版本


我试了这个 Go Playground - The Go Programming Language,它是可以工作的。 你确定你使用的是 Go v1.22 吗?

Massimo.Costa:

你确定你正在使用 Go v1.22 吗?

谢谢!问题就在这里,我需要更新我的 go mod 文件。下次就知道了,仅仅运行 go version 是不够的,mod 文件也必须更新。

检查升级到 Go 1.22 时的 go.mod 版本

谢谢!问题解决了。

我确信我使用了正确的版本,因为我能使用 r.PathValue()。也许 PathValue 是在更早的版本中引入的?

如果有人遇到这个问题,你可以从终端运行以下命令来更新它:

go mod edit -go=1.22

问题在于你混合使用了 http.Handlehttp.HandleFunc。Go 1.22 的新路由模式只适用于 http.Handle 方法,而 http.HandleFunc 目前还不支持模式匹配。

以下是正确的实现方式:

package main

import (
	"fmt"
	"log"
	"net/http"
)

func main() {
	// 使用 http.Handle 而不是 http.HandleFunc
	http.Handle("GET /articles/{id}", http.HandlerFunc(articles))
	
	log.Fatalln(http.ListenAndServe(":8080", nil))
}

func articles(w http.ResponseWriter, r *http.Request) {
	// 获取路径参数
	id := r.PathValue("id")
	fmt.Fprintf(w, "Article ID: %s\n", id)
}

或者使用更简洁的方式:

package main

import (
	"fmt"
	"log"
	"net/http"
)

func main() {
	http.HandleFunc("GET /articles/{id}", func(w http.ResponseWriter, r *http.Request) {
		id := r.PathValue("id")
		fmt.Fprintf(w, "Article ID: %s\n", id)
	})
	
	log.Fatalln(http.ListenAndServe(":8080", nil))
}

关键区别:

  1. http.Handle 接受模式字符串和 http.Handler 接口
  2. http.HandlerFunc 可以将函数转换为 http.Handler
  3. Go 1.22 为 http.Handlehttp.HandleFunc 都添加了模式匹配支持,但语法略有不同

测试你的路由:

curl http://localhost:8080/articles/123
# 输出: Article ID: 123

curl http://localhost:8080/articles/abc
# 输出: Article ID: abc

如果仍然遇到问题,请检查是否有其他路由冲突,或者尝试清理并重新构建:

go clean -cache
go run main.go
回到顶部