#go http.Handle和http.HandleFunc的区别
例子分析
package main
import (
"log"
"io"
"net/http"
)
type TestHandle struct {}
func (t TestHandle)ServeHTTP(w http.ResponseWriter, r *http.Request) {
_, _ = io.WriteString(w, "test1")
}
func TestHttp(w http.ResponseWriter, r *http.Request) {
_, _ = io.WriteString(w, "test2")
}
func main() {
testHandle := TestHandle{}
http.Handle("/test1", testHandle)
http.HandleFunc("/test2", TestHttp)
log.Fatal(http.ListenAndServe(":8080", nil).Error())
}
一眼可以看出来,
http.Handle
和http.HandleFunc
的区别是,前者需要声明一个结构体,然后实现ServeHTTP(http.ResponseWriter, *http.Request)
接口。后者直接传入一个 以(whttp.ResponseWriter, *http.Request)
为参数的函数指针。
http.Handle的底层调用
http.Handle("/test1", testHandle)
↓
func Handle(pattern string, handler Handler) { DefaultServeMux.Handle(pattern, handler) }
↓
func (mux *ServeMux) Handle(pattern string, handler Handler) {...}
↓
type Handler interface {
ServeHTTP(ResponseWriter, *Request)
}
可以看到
http.Handle
第二个参数是Handler
,是一个接口结构,所以通过实现接口,调用实例的原理,传进去的结构体只要实现了ServeHTTP
接口,在Handle
中就会注册(map结构,key是路由路径,value是实现ServeHTTP
接口的结构体),路由响应就会调用对用的响应函数了。
http.HandleFunc的底层调用
http.HandleFunc("/test2", TestHttp)
↓
func HandleFunc(pattern string, handler func(ResponseWriter, *Request)) {
DefaultServeMux.HandleFunc(pattern, handler)
}
↓
(mux *ServeMux) HandleFunc(pattern string, handler func(ResponseWriter,
*Request))
↓
mux.Handle(pattern, HandlerFunc(handler)
↓
type HandlerFunc func(ResponseWriter, *Request)
↓
func (f HandlerFunc) ServeHTTP(w ResponseWriter, r *Request) { f(w, r) }
一路看下来,
http.HandleFunc
主要是第二个参数是handler func(ResponseWriter, *Request)
。相当于直接把响应函数赋值给HandlerFunc
,HandlerFunc
是func(ResponseWriter, *Request)
类型,并且它实现了ServeHTTP
接口,里面会调用f,并且在路由响应时触发注册的响应函数被调用。
总结
因此,整个流程下来,http.Handle
和 http.HandleFunc
就是通过不同方式实现一个 ServeHTTP
接口,在路由选中时触发响应的。应用了对象封装,实现接口,多态的特性吧。