2012-11-06 8 views
46

Ich lerne Go durch eine App für GAE zu schreiben, und das ist Unterzeichnung einer Handler-Funktion:In Go-HTTP-Handlern, warum ist der ResponseWriter ein Wert, aber die Anforderung eines Zeigers?

func handle(w http.ResponseWriter, r *http.Request) {} 

Ich bin hier Zeiger Neuling, also warum ist das Request Objekt ein Zeiger, aber die ResponseWriter nicht ? Gibt es eine Notwendigkeit, es auf diese Weise zu haben, oder ist das nur, um eine Art fortgeschrittenen pointerbasierten Code zu ermöglichen?

Antwort

43

Was Sie für w bekommen, ist ein Zeiger auf den nicht exportierten Typ , aber als ResponseWriter ist eine Schnittstelle, die nicht sichtbar ist.

Von server.go:

type ResponseWriter interface { 
    ... 
} 

Auf der anderen Seite, r ist ein Zeiger auf eine konkrete Struktur, daher die Notwendigkeit, präzise es ausdrücklich:

Von request.go:

type Request struct { 
    ... 
} 
20

Die http.ResponseWriter ist eine Schnittstelle, und die vorhandenen Typen, die diese Schnittstelle implementieren, sind Zeiger. Das bedeutet, dass kein Zeiger auf diese Schnittstelle benötigt wird, da dieser bereits von einem Zeiger "unterstützt" wird. Dieses Konzept ist ein bisschen von einem der Go-Entwickler here beschrieben. Obwohl ein Typ, der http.ResponseWriter implementiert, kein Zeiger sein musste, wäre es nicht praktikabel, zumindest nicht innerhalb des Go http-Servers.

http.Request ist keine Schnittstelle, es ist nur eine Struktur, und da wir diese Struktur ändern und den Webserver diese Änderungen sehen wollen, muss es ein Zeiger sein. Wenn es nur ein Strukturwert wäre, würden wir nur eine Kopie davon modifizieren, die der Webserver, der unseren Code aufruft, nicht sehen konnte.

+1

Ich glaube nicht, dass das richtig ist. Werte hinter Zeigern können Schnittstellen genauso wie Werte implementieren, so dass hier keine Unterscheidung erforderlich ist. Ein Typ mit dem Basistyp int kann eine Schnittstelle erfüllen, ohne ein Zeiger zu sein oder von einem solchen unterstützt zu werden. – nemo

+1

Nun, ich wollte nicht andeuten, dass alle Dinge, die eine Schnittstelle implementieren, Zeiger sein müssen.Etwas wie ein ResponseWriter, der den Status des Wertes hinter der Schnittstelle ändern müsste, um irgendetwas Nützliches zu tun, und das erfordert, dass der Wert ein Zeigertyp ist (wie der Blogbeitrag, mit dem ich verlinkt habe, auch sagt). Aber ja, http.ResponseWriter könnte theoretisch durch einen int implementiert werden (dessen Methoden diesen int-Wert niemals ändern könnten). – nos

0

Ich denke, dass der Hauptgrund für das Request Objekt, das als Zeiger übergeben werden soll, das Feld Body ist. Für eine gegebene HTTP-Anfrage kann der Körper nur einmal gelesen werden. Wenn das Objekt Request geklont wurde, wie es wäre, wenn es nicht als Zeiger übergeben würde, hätten wir zwei Objekte mit unterschiedlichen Informationen darüber, wie viel vom Körper gelesen wurde.

0

Der Grund, warum es ein Zeiger auf Request ist, ist einfach: Änderungen an Request durch den Handler müssen für den Server sichtbar sein, so dass wir ihn nur als Referenz statt als Wert übergeben.

Wenn Sie in den net/http-Bibliothekscode eintauchen, werden Sie feststellen, dass ResponseWriter eine Schnittstelle zu einer nicht exportierten struct-Antwort ist und wir die Struktur als Referenz übergeben (wir geben einen Zeiger auf die Antwort) und nicht nach Wert. ResponseWriter ist eine Schnittstelle, die ein Handler zum Erstellen einer HTTP-Antwort verwendet. Das eigentliche Struktur-Backup von ResponseWriter ist die nicht-exportierte Struktur http.response. Da sie nicht exportiert wird, können Sie sie nicht direkt verwenden. Sie können es nur über die ResponseWriter-Schnittstelle verwenden.

Mit anderen Worten, beide Parameter werden als Referenz übergeben; Es ist nur so, dass die Methodensignatur einen ResponseWriter verwendet, der eine Schnittstelle zu einem Zeiger auf eine Struktur darstellt, so dass es aussieht, als ob sie nach Wert übergeben wird.

Verwandte Themen