2011-12-31 15 views
5

estoy confundido acerca de this bit of code from the HTTP package:función Ir a escribir

type HandlerFunc func(ResponseWriter, *Request) 
func (f HandlerFunc) ServeHTTP(w ResponseWriter, r *Request) { 
    f(w, r) 
} 

¿Por qué el método ServeHTTP tienen exactamente la misma firma que es de tipo - cuál es el punto?

 

Testing, he descubierto que si paso una función aleatoria (foo) a la HandlerFunc:

var bar = HandlerFunc(foo) 

bar se convierte en una instancia de HandlerFunc con foo como su método de ServeHTTP. Ahora estoy realmente confundido acerca de cómo funciona esto.

Si tengo más de un método en un tipo, ¿cómo sé cuál se adjuntará a la nueva instancia y con qué nombre u orden?

Respuesta

8

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 foopara 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?

+0

+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. –

+0

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

+0

@Tom: De nada, ¡me alegro de poder ayudar! Feliz año nuevo. :-) – ruakh