2009-11-21 20 views
10

Voglio sapere cosa sta succedendo qui.Funzione implementazione interfaccia

V'è l'interfaccia per un gestore http:

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

Questa implementazione Credo di capire.

type Counter int 

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

Dalla mia comprensione si è che il tipo di "Counter" implementa l'interfaccia dal momento che ha un metodo che ha la firma richiesto. Fin qui tutto bene. Quindi questo esempio è dato:

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); 

Qualcuno può approfondire perché o come queste varie funzioni combaciano?

risposta

12

Questo:

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

dice che qualsiasi tipo che soddisfa l'interfaccia Handler deve avere un metodo ServeHTTP. Quanto sopra sarebbe all'interno del pacchetto http.

type Counter int 

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

Inserisce un metodo sul tipo di contatore che corrisponde a ServeHTTP. Questo è un esempio che è separato dal seguente.

Dalla mia comprensione esso è che il tipo "Counter" implementa l'interfaccia dal momento che ha un metodo che ha la firma richiesto.

Proprio così.

La seguente funzione di per sé non funzionerà come 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"); 
} 

Il resto di questa roba è solo conviene quanto sopra in modo che possa essere un Handler.

Nel seguito, un HandlerFunc è una funzione che prende due argomenti, puntatore Conn e puntatore Request, e restituisce nulla. In altre parole, qualsiasi funzione che accetta questi argomenti e restituisce nulla può essere un HandlerFunc.

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

Qui ServeHTTP è un metodo aggiunto al tipo HandlerFunc:

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

Tutto ciò che fa è chiamare la funzione stessa (f) con gli argomenti dati.

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

Nella riga sopra, notFound è stato finagled in essere accettabile per l'interfaccia per Handler creando artificialmente un'istanza tipo fuori della funzione stessa e far funzionare nel metodo ServeHTTP per l'istanza. Ora è possibile utilizzare Handle404 con l'interfaccia Handler. È fondamentalmente una specie di trucco.

+0

Ok penso di averlo capito ora, la cosa che mi ha fatto inciampare è stata la conversione di notFound in HandlerFunc. Dopo aver riletto la sezione conversioni di go efficaci, è più chiaro come ciò possa essere applicato anche alle funzioni. http://golang.org/doc/effective_go.html#conversions – mbarkhau

1

Che cosa esattamente non capisci della seconda metà? È lo stesso schema di sopra. Invece di definire il tipo di contatore come int, definiscono una funzione chiamata notFound. Quindi creano un tipo di funzione chiamata HandlerFunc che accetta due parametri, una connessione e una richiesta. quindi creano un nuovo metodo chiamato ServeHTTP, che viene associato al tipo HandlerFunc. Handle404 è semplicemente un'istanza di questa classe che utilizza la funzione notFound.

+2

Sì, è la tipica programmazione funzionale di ordine superiore. Può essere fonte di confusione la prima volta che lo vedi e ti fa strada tra i tipi. – Suppressingfire

Problemi correlati