去功能打字

时间:2011-12-31 22:31:12

标签: function types go

我对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方法。现在我真的很困惑这是如何运作的。

如果我在一个类型上有多个方法,我怎么知道哪个方法将附加到新实例以及用什么名称或命令?

1 个答案:

答案 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方法。

这有意义吗?