Go 1.22中新HTTP路由器

Golang 1.22于2024年2月6日发布。该版本应用了相当多的更新。我非常感兴趣的一件事是增强的路由模式。借助此功能,我们可以创建动态路由参数,而无需第三方库。让我们进一步探索。

问题
在 golang 中创建一个 http 服务器非常简单。例如,如下面的代码片段所示。

package main

import (
    "fmt"
    
"net/http"
)

func IndexHandler(w http.ResponseWriter, r *http.Request) {
    fmt.Fprint(w,
"Hello from route /index")
}

func main() {
    http.HandleFunc(
"/index", IndexHandler)

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

当我们访问 localhost:8080/index 时,将收到来自路由 /index 的 Hello 响应。

正如你所看到的,在 IndexHandler 中会出现一些麻烦和问题,包括:

  • (1) 如何验证 HTTP 方法(无需重复检查 HTTP 方法)?
  • (2) 如何处理动态 URL 参数情况,如 /index/foo 或 index/bar?

解决方案:在Go 1.22 之前
要解决这个问题,最简单的办法就是使用现有的社区库。有很多 golang 库都支持这种方法,例如 mux、chi、echo 等等。例如,在 chi 中,你可以这样做:

package main

import (
    "fmt"
    
"net/http"

    
"github.com/go-chi/chi/v5"
)

func IndexHandler(w http.ResponseWriter, r *http.Request) {
    fmt.Fprint(w,
"Hello from route /index")
}

func DynamicHandler(w http.ResponseWriter, r *http.Request) {
    param := chi.URLParam(r,
"param")
    fmt.Fprintf(w,
"Hello from route /index/%s", param)
}

func main() {
    r := chi.NewRouter()

    r.Get(
"/index", IndexHandler)
    r.Get(
"/index/{param}", DynamicHandler)
    
    http.ListenAndServe(
":3000", r)


有了这个

  • (1) 我们不必在每个 http 处理程序中键入 if r.Method == "GET"。
  • (2) 我们可以轻松获取请求的 url 参数。

进入 Go 1.22
在 Go 1.22 中,我们只需使用标准库就能解决之前的问题。下面是一个例子:

package main

import (
    "fmt"
    
"net/http"
)

func IndexHandler(w http.ResponseWriter, r *http.Request) {
    fmt.Fprint(w,
"Hello from route /index")
}

func DynamicHandler(w http.ResponseWriter, r *http.Request) {
    param := r.PathValue(
"param")
    fmt.Fprintf(w,
"Hello from route /index/%s", param)
}

func main() {
    http.HandleFunc(
"GET /index", IndexHandler)
    http.HandleFunc(
"GET /index/{param}", DynamicHandler)

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

正如你所看到的,它看起来与现有库几乎一样。不同之处在于:
http 方法是在 url 路径之前定义的。要检索动态 url 参数的值,我们可以使用 r.PathValue。请注意,HTTP 方法区分大小写,因此 http 方法名称必须大写(GET,而不是 Get 或 get)。

结论
有了这个增强的路由模式,使用 golang 创建 http 服务器将变得更简单、更高效,因为标准库提供了两个重要的功能。当然,如果你想创建的 http 服务器具有复杂的功能,最好还是使用 golang 社区提供的网络框架/路由库。