使用 Go 处理 HTTP 请求主要涉及两件事:ServeMuxes
和 Handlers
。
- ServeMux本质上是一个 HTTP 请求路由器(或多路复用器)。它将传入的请求与预定义的 URL 路径列表进行比较,并在找到匹配时调用路径的关联 handler。
- handler 负责写入响应头和响应体。几乎任何对象都可以是 handler,只要它满足http.Handler接口即可。
必须实现ServeHTTP方法:ServeHTTP(http.ResponseWriter, *http.Request)
package mainimport ("log""net/http"
)func main() {mux := http.NewServeMux()rh := http.RedirectHandler("http://example.org", 307)mux.Handle("/foo", rh)log.Println("Listening...")http.ListenAndServe(":3000", mux)
}
- 在main函数中,我们使用http.NewServeMux函数创建了一个空的ServeMux。
然后我们使用http.RedirectHandler函数创建一个新的handler。 - 该handler将其接收的所有请求307重定向到http://example.org。
- 接下来我们使用mux.Handle函数向我们的新ServeMux注册它,因此它充当URL路径/foo的所有传入请求的handler。
- 最后,我们创建一个新服务并使用http.ListenAndServe函数开始监听传入的请求,并传入ServeMux给这个方法以匹配请求。
$ go run main.go
Listening...
自定义 handler
我们创建一个自定义 handler,它以当前本地时间的指定格式响应:
type timeHandler struct {format string
}func (th *timeHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {tm := time.Now().Format(th.format)w.Write([]byte("The time is: " + tm))
}
该示例中它是一个timeHandler结构,它同样可以是一个字符串或函数或其他任何东西),并且我们已经实现了一个带有签名ServeHTTP(http.ResponseWriter, *http.Request)
的方法。这就是我们实现一个 handler 所需的全部内容。
普通函数作为 handler
对于简单的情况,定义新的自定义类型和 ServeHTTP 方法感觉有点啰嗦。让我们看看另一个方法,我们利用 Go 的http.HandlerFunc类型来使正常的函数满足 Handler 接口。
任何具有签名func(http.ResponseWriter, *http.Request)
的函数都可以转换为 HandlerFunc 类型。这很有用,因为 HandleFunc 对象带有一个内置的ServeHTTP方法 - 这非常巧妙且方便 - 执行原始函数的内容。
package mainimport ("log""net/http""time"
)func timeHandler(w http.ResponseWriter, r *http.Request) {tm := time.Now().Format(time.RFC1123)w.Write([]byte("The time is: " + tm))
}func main() {mux := http.NewServeMux()// Convert the timeHandler function to a HandlerFunc typeth := http.HandlerFunc(timeHandler)// And add it to the ServeMuxmux.Handle("/time", th)log.Println("Listening...")http.ListenAndServe(":3000", mux)
}
将函数转换为HandlerFunc类型,然后将其添加到ServeMux的情况比较常见,Go提供了一个快捷的转换方法:mux.HandleFunc方法。
如果我们使用这个转换方法,main()函数将是这个样子:
func main() {mux := http.NewServeMux()mux.HandleFunc("/time", timeHandler)log.Println("Listening...")http.ListenAndServe(":3000", mux)
}