2009-11-21 14 views
10

Quiero saber qué está pasando aquí.Función que implementa la interfaz

No es la interfaz para un controlador HTTP:

type Handler interface { 
    ServeHTTP(*Conn, *Request) 
} 

Esta implementación Creo que entiendo.

type Counter int 

func (ctr *Counter) ServeHTTP(c *http.Conn, req *http.Request) { 
    fmt.Fprintf(c, "counter = %d\n", ctr); 
    ctr++; 
} 

Según mi entender es que el tipo "Contador" implementa la interfaz ya que tiene un método que tiene la firma requerida. Hasta aquí todo bien. Entonces se da este ejemplo:

func notFound(c *Conn, req *Request) { 
    c.SetHeader("Content-Type", "text/plain;", "charset=utf-8"); 
    c.WriteHeader(StatusNotFound); 
    c.WriteString("404 page not found\n"); 
} 

// Now we define a type to implement ServeHTTP: 
type HandlerFunc func(*Conn, *Request) 
func (f HandlerFunc) ServeHTTP(c *Conn, req *Request) { 
    f(c, req) // the receiver's a func; call it 
} 
// Convert function to attach method, implement the interface: 
var Handle404 = HandlerFunc(notFound); 

¿Puede alguien explicar por qué o cómo encajan estas varias funciones juntas?

Respuesta

12

Este:

type Handler interface { 
    ServeHTTP(*Conn, *Request) 
} 

dice que cualquier tipo que satisface la interfaz Handler debe tener un método ServeHTTP. Lo anterior estaría dentro del paquete http.

type Counter int 

func (ctr *Counter) ServeHTTP(c *http.Conn, req *http.Request) { 
    fmt.Fprintf(c, "counter = %d\n", ctr); 
    ctr++; 
} 

Esto pone un método en el tipo de contador que corresponde a ServeHTTP. Este es un ejemplo que está separado del siguiente.

Desde mi entendimiento es que el tipo "Contador" implementa la interfaz ya que cuenta con un método que tiene la firma requerida.

Así es.

La siguiente función por sí sola no va a funcionar como un Handler:

func notFound(c *Conn, req *Request) { 
    c.SetHeader("Content-Type", "text/plain;", "charset=utf-8"); 
    c.WriteHeader(StatusNotFound); 
    c.WriteString("404 page not found\n"); 
} 

El resto de este material es sólo apropiado lo anterior para que pueda ser un Handler.

A continuación, un HandlerFunc es una función que toma dos argumentos, puntero a Conn y puntero a Request y no devuelve nada. En otras palabras, cualquier función que tome estos argumentos y no devuelva nada puede ser HandlerFunc.

// Now we define a type to implement ServeHTTP: 
type HandlerFunc func(*Conn, *Request) 

Aquí ServeHTTP es un método añadido al tipo HandlerFunc:

func (f HandlerFunc) ServeHTTP(c *Conn, req *Request) { 
    f(c, req) // the receiver's a func; call it 
} 

único que hace es llamar a la función en sí (f) con los argumentos dados.

// Convert function to attach method, implement the interface: 
var Handle404 = HandlerFunc(notFound); 

En la línea anterior, notFound se ha finagled en ser aceptable para la interfaz para Handler creando artificialmente una instancia de tipo de la función en sí y haciendo la función en el método de ServeHTTP para la instancia. Ahora se puede usar Handle404 con la interfaz Handler. Básicamente es una especie de truco.

+0

Ok, creo que lo entiendo ahora, lo que me hizo tropezar fue la conversión de notFound a HandlerFunc. Después de releer la sección de conversiones de go efectivo, queda más claro cómo eso también puede aplicarse a las funciones. http://golang.org/doc/effective_go.html#conversions – mbarkhau

1

¿Qué exactamente no entiendes sobre la segunda mitad? Es el mismo patrón que el anterior. En lugar de definir el tipo de contador como int, definen una función llamada notFound. Luego crean un tipo de función llamada HandlerFunc que toma dos parámetros, una conexión y una solicitud. luego crean un nuevo método llamado ServeHTTP, que se vincula al tipo HandlerFunc. Handle404 es simplemente una instancia de esta clase que utiliza la función notFound.

+2

Sí, es una programación funcional típica de orden superior. Puede ser confuso la primera vez que lo vea y avance por los tipos. – Suppressingfire

Cuestiones relacionadas