astaxie / build-web-application-with-golang

A golang ebook intro how to build a web with golang
BSD 3-Clause "New" or "Revised" License
43.32k stars 10.64k forks source link

3.4 Go的http包详解 sayhelloName函数并没有实现ServeHTTP这个接口 #694

Open akkagao opened 8 years ago

akkagao commented 8 years ago

Handler是一个接口,但是前一小节中的# sayhelloName函数并没有实现ServeHTTP这个接口,为什么能添加呢?原来在http包里面还定义了一个类型HandlerFunc,我们定义的函数sayhelloName就是这个HandlerFunc调用之后的结果,这个类型默认就实现了ServeHTTP这个接口,即我们调用了HandlerFunc(f),强制类型转换f成为HandlerFunc类型,这样f就拥有了ServeHTTP方法

# sayhelloName函数并没有实现ServeHTTP这个接口
这句话让人感觉好像 函数可以实现接口?是我理解有问题吗?

JackHighBlack commented 7 years ago

这一节,大牛分析http包中的,我是是囫囵吞枣看过,汗颜

lanmeng-org commented 6 years ago

http包下server.go里定义了HandlerFunc类型, 这里实现了 ServeHTTP

// The HandlerFunc type is an adapter to allow the use of
// ordinary functions as HTTP handlers. If f is a function
// with the appropriate signature, HandlerFunc(f) is a
// Handler that calls f.
type HandlerFunc func(ResponseWriter, *Request)

// ServeHTTP calls f(w, r).
func (f HandlerFunc) ServeHTTP(w ResponseWriter, r *Request) {
    f(w, r)
}

在调用 http.HandleFunc("/", sayhelloName)注册路由时, 这里的 HandleFunc 方法会把第个参数转为 HandlerFunc类型.

http.HandleFunc

// HandleFunc registers the handler function for the given pattern
// in the DefaultServeMux.
// The documentation for ServeMux explains how patterns are matched.
func HandleFunc(pattern string, handler func(ResponseWriter, *Request)) {
    DefaultServeMux.HandleFunc(pattern, handler)
}

DefaultServeMux.HandleFunc

// HandleFunc registers the handler function for the given pattern.
func (mux *ServeMux) HandleFunc(pattern string, handler func(ResponseWriter, *Request)) {
    mux.Handle(pattern, HandlerFunc(handler))
}

转换例子:

handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {});
t := reflect.TypeOf(handler)
fmt.Print(t.Name())
//   输出: HandlerFunc