Go функция ввода - PullRequest
       16

Go функция ввода

5 голосов
/ 01 января 2012

Я не совсем понимаю, этот бит кода из пакета HTTP :

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 Ответ

8 голосов
/ 01 января 2012

Этот подход позволяет вам использовать функцию в контексте, который ожидает 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 способ.

Имеет ли это смысл?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...