http.Handler Interface
Teil des Abschnitts Objektorientierte Programmierung der GO-Journey von Coddy — Lektion 77 von 107.
Das http.Handler-Interface ist die Grundlage der Webserver-Architektur von Go. Es definiert, wie HTTP-Anfragen verarbeitet werden, und jeder Typ, der es implementiert, kann Web-Anfragen bedienen.
Die Schnittstelle ist bemerkenswert einfach:
type Handler interface {
ServeHTTP(ResponseWriter, *Request)
}Jeder Typ mit einer ServeHTTP-Methode kann HTTP-Anfragen verarbeiten. Hier ist ein benutzerdefinierter Handler:
type GreetHandler struct {
Greeting string
}
func (h GreetHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "%s, visitor!", h.Greeting)
}Sie können diesen Handler direkt mit einem Server verwenden:
handler := GreetHandler{Greeting: "Welcome"}
http.Handle("/greet", handler)Für einfachere Fälle bietet Go http.HandlerFunc an, einen Typ, mit dem Sie eine reguläre Funktion in einen Handler konvertieren können:
func hello(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "Hello!")
}
http.Handle("/hello", http.HandlerFunc(hello))Die Stärke dieser Schnittstelle wird deutlich, wenn man erkennt, dass Handler andere Handler umschließen können. Dies ermöglicht Middleware-Muster, bei denen Sie Logging, Authentifizierung oder andere querschnittliche Belange hinzufügen, ohne die ursprüngliche Handler-Logik zu ändern.
Aufgabe
EinfachLassen Sie uns ein einfaches HTTP-Handler-System bauen, das simuliert, wie Web-Anfragen verarbeitet werden! Da wir in dieser Umgebung keinen tatsächlichen HTTP-Server ausführen können, erstellen Sie Handler, die das http.Handler-Interface implementieren und demonstrieren, wie sie Anfragen verarbeiten, indem sie mit Mock-Request/Response-Objekten arbeiten.
Sie werden Ihren Code über zwei Dateien organisieren:
handlers.go: Definieren Sie Ihre benutzerdefinierten HTTP-Handler.Erstellen Sie ein
MockResponseWriter-Struct, das erfasst, was in eine HTTP-Antwort geschrieben würde. Es sollte den Antwortkörper als String speichern und eineWrite(data []byte) (int, error)-Methode implementieren, die Daten an den Körper anhängt. Fügen Sie eineBody() string-Methode hinzu, um die angesammelte Antwort abzurufen.Erstellen Sie ein
MockRequest-Struct mit den String-FeldernPathundMethod, um eine HTTP-Anfrage zu simulieren.Erstellen Sie nun zwei Handler-Structs, die das
http.Handler-Interface-Muster implementieren (mit einerServeHTTP-Methode, die einen*MockResponseWriterund einen*MockRequestentgegennimmt):WelcomeHandlermit einemMessage-Feld - schreibt die Nachricht gefolgt vom Pfad der AnfrageMethodHandler- schreibt verschiedene Antworten basierend auf der Anfragemethode:"Fetching data"für GET,"Creating resource"für POST und"Method not supported"für alles andere
main.go: Verarbeiten Sie Anfragen über Ihre Handler.Lesen Sie einen Handler-Typ (
welcomeodermethod) ein und lesen Sie dann die Anfragedetails. Für den Welcome-Handler lesen Sie zusätzlich die Willkommensnachricht ein.Erstellen Sie den entsprechenden Handler, bauen Sie einen Mock-Request und rufen Sie
ServeHTTPauf, um ihn zu verarbeiten. Geben Sie den Antwortkörper aus.
Die folgenden Eingaben werden bereitgestellt:
- Zeile 1: Handler-Typ (
welcomeodermethod) - Zeile 2: Anfragepfad
- Zeile 3: Anfragemethode
- Zeile 4 (nur für welcome): Willkommensnachricht
Zum Beispiel, gegeben:
welcome
/home
GET
Hello fromIhre Ausgabe sollte sein:
Hello from /homeUnd gegeben:
method
/api/users
POSTIhre Ausgabe sollte sein:
Creating resourceUnd gegeben:
method
/api/data
GETIhre Ausgabe sollte sein:
Fetching dataUnd gegeben:
method
/api/items
DELETEIhre Ausgabe sollte sein:
Method not supportedDiese Herausforderung demonstriert das Kernkonzept des http.Handler-Interfaces – jeder Typ mit einer ServeHTTP-Methode kann Anfragen verarbeiten. In realen Anwendungen stammen http.ResponseWriter und *http.Request aus der Standardbibliothek von Go, aber das Muster der Implementierung von Handlern bleibt genau gleich.
Spickzettel
Die Schnittstelle http.Handler ist die Grundlage der Webserver-Architektur von Go:
type Handler interface {
ServeHTTP(ResponseWriter, *Request)
}Jeder Typ mit einer ServeHTTP-Methode kann HTTP-Anfragen verarbeiten:
type GreetHandler struct {
Greeting string
}
func (h GreetHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "%s, visitor!", h.Greeting)
}Registrieren Sie einen Handler beim Server:
handler := GreetHandler{Greeting: "Welcome"}
http.Handle("/greet", handler)Verwenden Sie für einfachere Fälle http.HandlerFunc, um eine Funktion in einen Handler zu konvertieren:
func hello(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "Hello!")
}
http.Handle("/hello", http.HandlerFunc(hello))Handler können andere Handler umschließen, was Middleware-Muster für Logging, Authentifizierung oder andere querschnittliche Belange ermöglicht.
Probier es selbst
package main
import (
"bufio"
"fmt"
"os"
)
func main() {
scanner := bufio.NewScanner(os.Stdin)
// Handler-Typ lesen
scanner.Scan()
handlerType := scanner.Text()
// Anfragepfad lesen
scanner.Scan()
path := scanner.Text()
// Anfragemethode lesen
scanner.Scan()
method := scanner.Text()
// Mock-Anfrage erstellen
request := &MockRequest{
Path: path,
Method: method,
}
// Mock-Response-Writer erstellen
response := &MockResponseWriter{}
// TODO: Basierend auf handlerType den entsprechenden Handler erstellen
// Wenn handlerType "welcome" ist, die Willkommensnachricht lesen und WelcomeHandler erstellen
// Wenn handlerType "method" ist, MethodHandler erstellen
// ServeHTTP auf dem Handler mit response und request aufrufen
if handlerType == "welcome" {
scanner.Scan()
message := scanner.Text()
// TODO: WelcomeHandler mit der Nachricht erstellen und ServeHTTP aufrufen
_ = message // Diese Zeile bei der Implementierung entfernen
} else if handlerType == "method" {
// TODO: MethodHandler erstellen und ServeHTTP aufrufen
}
// Den Response-Body ausgeben
fmt.Println(response.Body())
}
Diese Lektion enthält ein kurzes Quiz. Starte die Lektion, um es zu beantworten und deinen Fortschritt zu speichern.
Alle Lektionen in Objektorientierte Programmierung
1Grundlagen der Go OOP
Externe DateienGo Workspace & ModulePackages & ImportsExportierte vs. nicht-exportierte NamenEinführung in OOP in GoStructs als KlassenMethoden für Structs definierenPointer- vs. Value-ReceiverStruct-InitialisierungKonstruktor-FunktionenZusammenfassung – Einfacher Taschenrechner4Interfaces
Einführung in InterfacesImplizite ImplementierungInterface als VertragLeeres Interface (any)Type AssertionType SwitchInterface-KompositionStringer & Error InterfacesRückblick - Formen-Rechner7Kapselung
Exportierte vs. nicht exportierte FelderKapselung auf Paket-EbeneGetter- & Setter-MethodenInformation Hiding in GoZusammenfassung - Studierendendatensätze10Generics (Go 1.18+)
Einführung in GenericsTypparameterType ConstraintsGenerische StructsWorkaround für generische MethodenZusammenfassung – Generische Collection2Vertiefung: Typen & Structs
Basis- & zusammengesetzte TypenBenutzerdefinierte TypdefinitionenStruct TagsAnonyme StructsVerschachtelte StructsZero Values & StandardwerteZusammenfassung - Kontaktbuch5Komposition statt Vererbung
Warum Go keine Vererbung hatGrundlagen des Struct EmbeddingMethod PromotionEinbetten mehrerer StructsEmbedding vs. AggregationShadowing eingebetteter MethodenZusammenfassung – Mitarbeiter-Hierarchie8Fehlerbehandlung & OOP
Das error-InterfaceEigene FehlertypenError Wrapping (fmt.Errorf)Sentinel-Fehlererrors.Is() und errors.As()Panic, Defer und RecoverZusammenfassung – Datei-Parser11Standardbibliothek & OOP
io.Reader & io.Writersort.Interfacefmt.Stringer Interfaceencoding/json mit Structshttp.Handler InterfaceZusammenfassung - REST-API-Modelle3Zeiger & Speicher
Zeiger-Grundlagen in GoZeiger auf StructsWertübergabe vs. ReferenzübergabeDie new() FunktionGarbage Collection in GoWiederholung – Linked List Builder6Polymorphismus in Go
Polymorphismus über InterfacesDuck Typing in GoInterface-ErfüllungsregelnPolymorphe CollectionsDependency InjectionZusammenfassung – Payment Processor9Nebenläufigkeit & OOP
Goroutines GrundlagenChannels & KommunikationGepufferte vs. ungepufferte ChannelsSelect-Anweisungsync.Mutex & sync.RWMutexsync.WaitGroupThread-sicheres Struct-DesignZusammenfassung - Worker Pool