Este enfoque le permite utilizar una función en un contexto que está esperando un Handler
.
Lo que pasa es que hay una interfaz de Handler
:
type Handler interface {
ServeHTTP(ResponseWriter, *Request)
}
y varias funciones se declaran aceptar los parámetros que se declaran pertenecer a esta interfaz — por ejemplo:
func TimeoutHandler(h Handler, ns int64, msg string) Handler {
f := func() <-chan int64 {
return time.After(ns)
}
return &timeoutHandler{h, f, msg}
}
Lo que esto significa es que cuando invoca una función de este tipo, debe pasar un objeto perteneciente a un tipo que satisface esta interfaz, es decir, un tipo que tiene un ServeHTTP
método con la firma apropiada. (. En Go, a diferencia de algunos idiomas, un tipo no necesita implementar una interfaz explícita, sólo se necesita tener los métodos especificados por la interfaz)
Por lo tanto, el código de fragmento que cito:
type HandlerFunc func(ResponseWriter, *Request)
func (f HandlerFunc) ServeHTTP(w ResponseWriter, r *Request) {
f(w, r)
}
crea un tipo HandlerFunc
que se basa en func(ResponseWriter, *Request)
, pero aumenta el tipo con un método llamado ServeHTTP
con una firma apropiada, de modo que satisfaga la interfaz Handler
. Este método ServeHTTP
simplemente llama a la función en sí. Por lo tanto, si f
es una función con la firma correcta, se podría escribir algo como esto:
var h HandlerFunc = f // h == f, but converted to a HandlerFunc
// so it satisfies the Handler interface.
TimeoutHandler(h, 1000000, "timed out")
Para aclarar un par de cosas acerca de esto:
Testing, descubrí que si paso al azar función (foo
) a la HandlerFunc
:
var bar = HandlerFunc(foo)
bar
se convierte en una instancia de HandlerFunc
con foo
como su ServeHTTP
método. Ahora estoy realmente confundido acerca de cómo funciona esto.
En primer lugar, es más correcto decir que usted ha convertido una función aleatoria foo
para escribir HandlerFunc
, en lugar de que usted tiene pasa a la función HandlerFunc
como si fuera un HandlerFunc
función. (La notación HandlerFunc(foo)
es un encasillado, porque puede igual de bien escribir var bar HandlerFunc = foo
y dejar que la conversión ocurra de manera implícita.)
En segundo lugar, es más correcto decir que bar
tiene un método ServeHTTP
que invocafoo
, que foo
propio en realidad es el método ServeHTTP
.
¿Tiene sentido?
+1 para la explicación. Es genial que las funciones se puedan tratar de la misma manera que los objetos cuando se trata de interfaces satisfactorias. –
Gracias, esto hace las cosas mucho más claras. Ir es realmente un lenguaje inusual, pero por dentro, todo es muy simple. Feliz año nuevo, por cierto :). – thwd
@Tom: De nada, ¡me alegro de poder ayudar! Feliz año nuevo. :-) – ruakh