以下函数是如何实现的?
func handle(pattern string, handler interface{}) {
// ... what goes here? ...
http.Handle(pattern, ?)
}
handle("/foo", func(w http.ResponseWriter, r http.Request) { io.WriteString(w, "foo") }
handle("/bar", BarHandler{})
handle()被传递一个与http类型匹配的函数。HandlerFunc或实现http的类型。处理程序接口。
与其求助于反射,不如这样做:
func handle(pattern string, handler interface{}) {
var h http.Handler
switch handler := handler.(type) {
case http.Handler:
h = handler
case func(http.ResponseWriter, *http.Request):
h = http.HandlerFunc(handler)
default:
// error
}
http.Handle(pattern, h)
}
首先,我们需要在Java/C#的术语中引入术语"反射",在C++的术语中介绍RTTI。其实很简单。编译器在运行时保存数据以查明实例var i SomeType
的类型。Go支持反射,这就是它在运行时发现handler
类型的方法。
handle
函数使用反射。的粗略示例
package main
import ("reflect";"http")
type fakeHandler struct{}
func (frw *fakeHandler) ServeHTTP(http.ResponseWriter, *http.Request) {}
func handle(pattern string, handler interface{}) {
handlerInterface := reflect.TypeOf(new(http.Handler)).Elem()
handlerFunction := reflect.TypeOf(new(http.HandlerFunc)).Elem()
t := reflect.TypeOf(handler)
if t.Implements(handlerInterface) {fmt.Println("http.Handler")}
//http.HandlerFunc is a different type than
// func(http.ResponseWriter, *http.Request), but we can do
// var hf HandlerFunc = func(http.ResponseWriter, *http.Request){}
if t.AssignableTo(handlerFunction) {fmt.Println("http.HandleFunc")}
}
func f(http.ResponseWriter, *http.Request) {}
func main() {
handle("",&fakeHandler{})
handle("",f)
}