2009-11-21 8 views
10

Je veux savoir ce qui se passe ici.Fonction implémentant l'interface

Il est l'interface pour un gestionnaire http:

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

Cette mise en œuvre, je pense que je comprends. D'après ce que j'ai compris, c'est que le type "Counter" implémente l'interface car il a une méthode qui a la signature requise. Jusqu'ici tout va bien. Alors cet exemple est donné:

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

Quelqu'un peut-il expliquer pourquoi et comment ces différentes fonctions s'emboîtent?

Répondre

12

Ce:

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

dit que tout type qui satisfait l'interface Handler doit avoir une méthode ServeHTTP. Ce qui précède serait à l'intérieur du paquet http.

type Counter int 

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

Ceci met une méthode sur le type Counter qui correspond à ServeHTTP. Ceci est un exemple séparé des suivants.

De ma compréhension, il est que le type « compteur » implémente l'interface car il a une méthode qui a la signature requise.

C'est vrai.

La fonction suivante par lui-même ne fonctionnera pas comme 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"); 
} 

Le reste de ce genre de choses est normal que ce qui précède pour qu'il puisse être un Handler.

Dans ce qui suit, un HandlerFunc est une fonction qui prend deux arguments, pointeur -Conn et pointeur vers Request, et ne retourne rien. En d'autres termes, toute fonction qui prend ces arguments et ne renvoie rien peut être un HandlerFunc.

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

Ici ServeHTTP est une méthode ajoutée au type HandlerFunc:

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

Tout ce qu'il fait est d'appeler la fonction elle-même (f) avec les arguments donnés.

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

Dans la ligne ci-dessus, a été notFound finagled en étant acceptable pour l'interface pour Handler en créant artificiellement une instance de type de la fonction elle-même et en faisant la fonction dans le procédé ServeHTTP pour l'instance. Maintenant Handle404 peut être utilisé avec l'interface Handler. C'est fondamentalement une sorte de tour.

+0

Ok, je pense que je comprends maintenant, la chose qui m'a fait trébucher était la conversion de notFound à HandlerFunc. Après avoir relu la section des conversions d'efficacité, il est plus clair comment cela peut également s'appliquer aux fonctions. http://golang.org/doc/effective_go.html#conversions – mbarkhau

1

Que ne comprenez-vous pas exactement au sujet de la deuxième moitié? C'est le même modèle que ci-dessus. Au lieu de définir le type Compteur comme int, ils définissent une fonction appelée notFound. Ils créent ensuite un type de fonction appelé HandlerFunc qui prend deux paramètres, une connexion et une requête. ils créent ensuite une nouvelle méthode appelée ServeHTTP, qui est liée au type HandlerFunc. Handle404 est simplement une instance de cette classe qui utilise la fonction notFound.

+2

Oui, c'est une programmation fonctionnelle typique d'ordre supérieur. Il peut être déroutant la première fois que vous le voyez et travaillez votre chemin à travers les types. – Suppressingfire