处理器
一个处理器就是实现了Handler这个接口:
type Handler interface {
ServeHTTP(ResponseWriter, *Request)
}
实现一个处理器:
//定义一个处理器
type MyHandler struct{}
//实现Handler接口
func (h *MyHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
fmt.Fprintln(w, "hi")
}
func main() {
handler := MyHandler{}
//将处理器绑定在服务器上
server := http.Server{
Addr: "127.0.0.1:8000",
Handler: &handler,
}
server.ListenAndServe()
}
多路复用器DefaultServeMux是一个特殊的处理器,它的任务是根据请求的URL将请求重定向到不同的处理器。DefaultServeMux是http包默认提供的一个多路复用器:
//定义多个处理器
type h1 struct{}
func (h1 *h1) ServeHTTP(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "h1")
}
type h2 struct{}
func (h2 *h2) ServeHTTP(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "h2")
}
func main() {
h1 := h1{}
h2 := h2{}
//nil表明服务器使用默认的多路复用器DefaultServeMux
server := http.Server{
Addr: "0.0.0.0:8080",
Handler: nil,
}
//handle函数调用的是多路复用器DefaultServeMux.Handle方法
http.Handle("/h1", &h1)
http.Handle("/h2", &h2)
server.ListenAndServe()
}
处理器函数
处理器函数就是与ServeHTTP方法拥有相同签名的函数。
处理器函数的实现原理:Go语言拥有一种HandlerFunc函数类型,它可以把一个带有正确签名的函数f转换成一个带有方法f的Handler:
func hel(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "hello, world!")
}
h := HandlerFunc(hel) //将处理器函数转换成处理器
Handler的定义:
type HandlerFunc func(ResponseWriter, *Request)
// 在ServeHTTP方法里调用 f(w, r).
func (f HandlerFunc) ServeHTTP(w ResponseWriter, r *Request) {
f(w, r)
}
处理器函数只不过是创建处理器的便捷方法而已:
func b1(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "hello")
}
func main() {
http.HandleFunc("/b1", b1) //使用http包默认的多路复用器实例绑定
http.ListenAndServe("127.0.0.1:8080", nil) //使用http包默认的服务器实例,并开启监听
}
串联多个处理器和处理器函数
诸如日志记录、安全检查和错误处理这样的操作常称为横切点关注,虽然这些操作非常常见,但是为了防止代码重复和代码依赖问题,我们又不希望这些操作和正常的代码混在一起。所以,我们可以使用串联技术分隔代码中的横切关注点。
func hello(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "hello world!!")
}
func log(h http.HandlerFunc) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
fmt.Printf(" time: %s| handlerfunc:%s\n", time.Now().String(), runtime.FuncForPC(reflect.ValueOf(h).Pointer()).Name())
h(w, r)
}
}
func main() {
http.HandleFunc("/", log(hello))
http.ListenAndServe(":8080", nil)
}
串联多个处理器时:
func log22(h http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
...
h.ServeHTTP(w, r)
})
}
多路复用器
ServeMux是一个HTTP请求多路复用器,它负责接收HTTP请求并根据请求中的URL将请求重定向到正确的处理器。ServeMux本身是处理器。DefaultServeMux是ServeMux的一个实例。
URL处理规则:被绑定的URL不以/结尾,那么它只会与完全相同的URL匹配。被绑定的URL以/结尾,那么只有前缀相同,那么ServeMux也会匹配两个URL。
ServeMux的一个缺陷是无法使用变量实现URL模式匹配,第三方库HttpRouter则可以:
func hee(w http.ResponseWriter, r *http.Request, p httprouter.Params) {
fmt.Fprintf(w, "hello!%s\n", p.ByName("name"))
}
func main() {
mux := httprouter.New()
mux.GET("/hello/:name", hee)
mux.GET("/hello/", hee)
s := http.Server{
Addr: "127.0.0.1:8080",
Handler: mux,
}
s.ListenAndServe()
}