Go 的 net/http
包为 HTTP 协议提供了许多功能。它做得不太好的一件事是复杂请求路由,比如将请求 URL 细分为单个参数。幸运的是,有一个非常流行的包可以做到这一点,它以 Go 社区良好的代码质量而闻名。在本示例中,你将看到如何使用 gorilla/mux
包创建带有命名参数、GET/POST 处理程序和域限制的路由。
gorilla/mux
包gorilla/mux
是一个适应 Go 的默认 HTTP 路由器的包。它附带了许多功能,可以提高编写 Web 应用程序时的生产力。它还符合 Go 的默认请求处理程序签名 func (w http.ResponseWriter, r *http.Request)
,因此该包可以与其他 HTTP 库(如中间件或现有应用程序)混合和匹配。使用 go get
命令从 GitHub 安装包,如下所示
go get -u github.com/gorilla/mux
首先创建一个新的请求路由器。路由器是 Web 应用程序的主路由器,稍后将作为参数传递给服务器。它将接收所有 HTTP 连接,并将其传递给你将在其上注册的请求处理程序。你可以像这样创建一个新路由器
r := mux.NewRouter()
一旦你有了新的路由器,你就可以像往常一样注册请求处理程序。唯一的区别是,你不再调用 http.HandleFunc(...)
,而是像这样在路由器上调用 HandleFunc
:r.HandleFunc(...)
。
gorilla/mux
路由器最大的优势是能够从请求 URL 中提取片段。例如,这是应用程序中的一个 URL
/books/go-programming-blueprint/page/10
要让请求处理程序与上面提到的 URL 匹配,你需要用 URL 模式中的占位符替换动态片段,如下所示
r.HandleFunc("/books/{title}/page/{page}", func(w http.ResponseWriter, r *http.Request) {
// get the book
// navigate to the page
})
最后一步是从这些片段中获取数据。该包附带了函数 mux.Vars(r)
,它将 http.Request
作为参数,并返回片段的映射。
func(w http.ResponseWriter, r *http.Request) {
vars := mux.Vars(r)
vars["title"] // the book title slug
vars["page"] // the page
}
您是否曾经想过 http.ListenAndServe(":80", nil)
中的 nil
意味着什么?它是 HTTP 服务器的主路由器的参数。默认情况下它是 nil
,这意味着使用 net/http
包的默认路由器。要使用您自己的路由器,请用路由器 r
的变量替换 nil
。
http.ListenAndServe(":80", r)
这是您可以用来尝试在本示例中学习到的内容的完整代码。
package main
import (
"fmt"
"net/http"
"github.com/gorilla/mux"
)
func main() {
r := mux.NewRouter()
r.HandleFunc("/books/{title}/page/{page}", func(w http.ResponseWriter, r *http.Request) {
vars := mux.Vars(r)
title := vars["title"]
page := vars["page"]
fmt.Fprintf(w, "You've requested the book: %s on page %s\n", title, page)
})
http.ListenAndServe(":80", r)
}
gorilla/mux
路由器的功能将请求处理程序限制为特定的 HTTP 方法。
r.HandleFunc("/books/{title}", CreateBook).Methods("POST")
r.HandleFunc("/books/{title}", ReadBook).Methods("GET")
r.HandleFunc("/books/{title}", UpdateBook).Methods("PUT")
r.HandleFunc("/books/{title}", DeleteBook).Methods("DELETE")
将请求处理程序限制为特定的主机名或子域。
r.HandleFunc("/books/{title}", BookHandler).Host("www.mybookstore.com")
将请求处理程序限制为 http/https。
r.HandleFunc("/secure", SecureHandler).Schemes("https")
r.HandleFunc("/insecure", InsecureHandler).Schemes("http")
将请求处理程序限制为特定的路径前缀。
bookrouter := r.PathPrefix("/books").Subrouter()
bookrouter.HandleFunc("/", AllBooks)
bookrouter.HandleFunc("/{title}", GetBook)