Этот подход позволяет вам использовать функцию в контексте, который ожидает Handler
.
Что происходит, есть Handler
интерфейс:
type Handler interface {
ServeHTTP(ResponseWriter, *Request)
}
и объявлены различные функции для приема параметров, которые объявлены как принадлежащие этому интерфейсу & mdash; например:
func TimeoutHandler(h Handler, ns int64, msg string) Handler {
f := func() <-chan int64 {
return time.After(ns)
}
return &timeoutHandler{h, f, msg}
}
Это означает, что когда вы вызываете такую функцию, вы должны передать объект, принадлежащий типу, который удовлетворяет этому интерфейсу, то есть типу, который имеет ServeHTTP
метод с соответствующей подписью. (В Go, в отличие от некоторых языков, типу не нужно явно реализовывать интерфейс, ему просто нужно иметь методы, определенные интерфейсом.)
Итак, фрагмент кода, который вы цитируете:
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
) в HandlerFunc
:
var bar = HandlerFunc(foo)
bar
становится экземпляром HandlerFunc
с foo
в качестве метода ServeHTTP
. Теперь я действительно не понимаю, как это работает.
Во-первых, правильнее будет сказать, что вы преобразовали случайную функцию foo
в тип HandlerFunc
, а не что передали функция до HandlerFunc
, как если бы HandlerFunc
была функцией. (Обозначение HandlerFunc(foo)
относится к типу; вы также можете написать var bar HandlerFunc = foo
и позволить преобразованию происходить неявно.)
Во-вторых, правильнее будет сказать, что bar
имеет метод ServeHTTP
, который вызывает foo
, чем то, что сам foo
на самом деле является * ServeHTTP
способ.
Имеет ли это смысл?