Go网络编程-Routing (using gorilla/mux)
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(…)。
URL参数
gorilla/mux路由器的最大优势是能够从请求URL中提取片段。例如,这是你应用程序中的一个URL:
/books/go-programming-blueprint/page/10
这个URL有两个动态片段: * 书籍标题slug(go-programming-blueprint) * 页面(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服务器的路由器
你是否曾经想知道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)