我对this bit of code from the HTTP package感到困惑:
type HandlerFunc func(ResponseWriter, *Request)
func (f HandlerFunc) ServeHTTP(w ResponseWriter, r *Request) {
f(w, r)
}
为什么ServeHTTP
方法与其类型具有完全相同的签名 - 重点是什么?
测试,我发现如果我将随机函数(foo
)传递给HandlerFunc
:
var bar = HandlerFunc(foo)
bar
成为HandlerFunc
的实例,foo
作为ServeHTTP
方法。现在我真的很困惑这是如何运作的。
如果我在一个类型上有多个方法,我怎么知道哪个方法将附加到新实例以及用什么名称或命令?
答案 0 :(得分:8)
此方法允许您在期望Handler
的上下文中使用函数。
会发生什么,有一个Handler
界面:
type Handler interface {
ServeHTTP(ResponseWriter, *Request)
}
并声明各种函数接受声明属于此接口的参数 - 例如:
func TimeoutHandler(h Handler, ns int64, msg string) Handler {
f := func() <-chan int64 {
return time.After(ns)
}
return &timeoutHandler{h, f, msg}
}
这意味着当你调用这样一个函数时,你必须传入属于满足这个接口的类型的对象,也就是说,一个具有{{的类型1}}具有适当签名的方法。 (在Go中,与某些语言不同,类型不需要显式实现接口,它只需要具有接口指定的方法。)
所以,你引用的代码片段:
ServeHTTP
创建一个基于type HandlerFunc func(ResponseWriter, *Request)
func (f HandlerFunc) ServeHTTP(w ResponseWriter, r *Request) {
f(w, r)
}
的类型HandlerFunc
,但使用带有适当签名的func(ResponseWriter, *Request)
方法扩充该类型,以使其满足ServeHTTP
接口。这个Handler
方法只调用函数本身。因此,如果ServeHTTP
是具有正确签名的函数,您可以编写如下内容:
f
澄清一些关于此的事情:
测试,我发现如果我将随机函数(
var h HandlerFunc = f // h == f, but converted to a HandlerFunc // so it satisfies the Handler interface. TimeoutHandler(h, 1000000, "timed out")
)传递给foo
:var bar = HandlerFunc(foo)
HandlerFunc
成为bar
的实例,HandlerFunc
作为foo
方法。现在我真的很困惑这是如何运作的。
首先,说你已经转换一个随机函数ServeHTTP
来输入foo
,而不是你那个'更为正确ve 将函数传递给 HandlerFunc
,就好像HandlerFunc
是一个函数一样。 (HandlerFunc
表示法是一个类型转换;您也可以写HandlerFunc(foo)
并隐式转换。)
其次,说var bar HandlerFunc = foo
有一个调用 bar
的{{1}}方法,而不是ServeHTTP
本身实际 foo
方法。
这有意义吗?