例子
先看一个简单的例子:
package main
import (
"fmt"
"net/http"
)
type HelloHandler struct{}
func (h HelloHandler) ServeHTTP (w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "Hello Handler!")
}
func hello (w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "Hello!")
}
func main() {
server := http.Server{
Addr: "127.0.0.1:8080",
}
helloHandler := HelloHandler{}
http.Handle("/hello1", helloHandler)
http.HandleFunc("/hello2", hello)
server.ListenAndServe()
}
上述代码启动了一个 http 服务器,监听 8080 端口,分别实现了 /hello1 和 /hello2 两个路由。实现这两个路由的方法有点不同,一个使用 http.Handle,另一个使用 http.HandleFunc ,下面来看看这两个之间的区别;
http.Handle
首先,简单分析一下 http.Handle(pattern string, handler Handler),http.Handle(pattern string, handler Handler) 接收两个参数,一个是路由匹配的字符串,另外一个是 Handler 类型的值:
func Handle(pattern string, handler Handler) { DefaultServeMux.Handle(pattern, handler) }
然后由继续调用 DefaultServeMux.Handle(pattern string, handler Handler),该函数接收的参数与上面的函数一样:
func (mux *ServeMux) Handle(pattern string, handler Handler) {
...
}
这个 Handler 类型是什么呢,其实它就是一个接口,包含一个 ServeHttp() 的方法:
type Handler interface {
ServeHTTP(ResponseWriter, *Request)
}
所以,传入 http.Handle(pattern string, handler Handler) 第二个参数必须实现 ServeHTTP 这个方法,当接收到一个匹配路由的请求时,会调用该方法。
http.HandleFunc
该方法接收两个参数,一个是路由匹配的字符串,另外一个是 func(ResponseWriter, *Request) 类型的函数:
func HandleFunc(pattern string, handler func(ResponseWriter, *Request)) {
DefaultServeMux.HandleFunc(pattern, handler)
}
然后继续调用 DefaultServeMux.HandleFunc(pattern, handler):
func (mux *ServeMux) HandleFunc(pattern string, handler func(ResponseWriter, *Request)) {
mux.Handle(pattern, HandlerFunc(handler))
}
可以看到,这里把 handler 转换成了 HandlerFunc 类型,而 HandlerFunc 类型则如下所示:
type HandlerFunc func(ResponseWriter, *Request)
func (f HandlerFunc) ServeHTTP(w ResponseWriter, r *Request) {
f(w, r)
}
该类型实现了 ServeHTTP 接口,所以其也可以转换成 Handler 类型,接下来调用 mux.Handle(pattern string, handler Handler) 就跟 http.Handle 的流程是一样的了。