Methodenverkettung
Teil des Abschnitts Objektorientierte Programmierung der GO-Journey von Coddy — Lektion 81 von 107.
Method Chaining (Methodenverkettung) ist eine Technik, bei der Methoden das Empfängerobjekt zurückgeben, sodass mehrere Methodenaufrufe in einer einzigen Anweisung miteinander verknüpft werden können. Sie haben dies bereits beim Builder-Muster gesehen, aber es handelt sich um ein eigenständiges Konzept, das in vielen Kontexten nützlich ist.
Der Schlüssel liegt darin, von jeder Methode einen Zeiger auf das Struct zurückzugeben:
type Query struct {
table string
columns []string
where string
limit int
}
func (q *Query) Select(cols ...string) *Query {
q.columns = cols
return q
}
func (q *Query) From(table string) *Query {
q.table = table
return q
}
func (q *Query) Where(condition string) *Query {
q.where = condition
return q
}
func (q *Query) Limit(n int) *Query {
q.limit = n
return q
}Jetzt können Sie diese Aufrufe flüssig verketten:
query := &Query{}
query.Select("name", "email").From("users").Where("active = true").Limit(10)Dies liest sich im Vergleich zu separaten Anweisungen fast wie natürliche Sprache. Method Chaining funktioniert am besten, wenn Operationen ein Objekt konfigurieren oder modifizieren, ohne andere Werte zurückgeben zu müssen. Es wird häufig in Query Buildern, Konfigurations-APIs und Test-Assertion-Bibliotheken verwendet.
Denken Sie daran, dass jede Methode einen Pointer-Receiver verwenden muss und *StructType zurückgeben muss, damit die Verkettung ordnungsgemäß funktioniert.
Aufgabe
EinfachLassen Sie uns einen fließenden HTML-Element-Builder erstellen, der Method Chaining verwendet, um HTML-Tags mit Attributen und Inhalten zu konstruieren! Dies ist eine praktische Anwendung von Method Chaining – Sie erstellen eine API, die sich beim Erstellen von HTML-Elementen fast wie natürliche Sprache liest.
Sie werden Ihren Code auf zwei Dateien verteilen:
element.go: Definieren Sie Ihren HTML-Element-Builder mit verkettbaren Methoden.Erstellen Sie ein
Element-Struct, das den Tag-Namen, eine Map von Attributen (String zu String) und den inneren Inhalt speichert. Erstellen Sie diese verkettbaren Methoden, die jeweils*Elementzurückgeben:NewElement(tag string)- Konstruktor, der ein neues Element mit dem angegebenen Tag-Namen und einer initialisierten (leeren) Attribut-Map erstelltAttr(key, value string)- fügt dem Element ein Attribut hinzuID(id string)- Komfortmethode, die das "id"-Attribut setztClass(class string)- Komfortmethode, die das "class"-Attribut setztContent(text string)- setzt den inneren Inhalt des Elements
Fügen Sie eine
Render()-Methode hinzu, die den HTML-String zurückgibt. Attribute sollten in alphabetischer Reihenfolge nach dem Schlüssel erscheinen. Das Format ist:<tag attr1="value1" attr2="value2">content</tag>Wenn keine Attribute vorhanden sind, rendern Sie einfach
<tag>content</tag>. Wenn kein Inhalt vorhanden ist, rendern Sie<tag attr="value"></tag>.main.go: Erstellen Sie HTML-Elemente mithilfe von Method Chaining.Lesen Sie den Tag-Namen ein und lesen Sie dann die Anzahl der auszuführenden Operationen. Jede Operation ist eine der folgenden:
idgefolgt vom ID-Wertclassgefolgt vom Class-Wertattrgefolgt vom Attributnamen und -wert (zwei Zeilen)contentgefolgt vom Inhaltstext
Verketten Sie alle Operationen fließend miteinander und geben Sie dann das gerenderte HTML aus.
Die folgenden Eingaben werden bereitgestellt:
- Zeile 1: Tag-Name
- Zeile 2: Anzahl der Operationen
- Folgende Zeilen: Operationstyp und Wert(e)
Zum Beispiel, gegeben:
div
3
id
container
class
main-content
content
Hello WorldIhre Ausgabe sollte sein:
<div class="main-content" id="container">Hello World</div>Und gegeben:
a
3
attr
href
https://example.com
attr
target
_blank
content
Click hereIhre Ausgabe sollte sein:
<a href="https://example.com" target="_blank">Click here</a>Und gegeben:
input
2
attr
type
text
attr
placeholder
Enter nameIhre Ausgabe sollte sein:
<input placeholder="Enter name" type="text"></input>Und gegeben:
p
1
content
Simple paragraphIhre Ausgabe sollte sein:
<p>Simple paragraph</p>Beachten Sie, wie Method Chaining es Ihnen ermöglicht, Elemente Schritt für Schritt auf lesbare Weise aufzubauen. Jede Methode modifiziert das Element und gibt es zurück, sodass der nächste Methodenaufruf direkt angehängt werden kann.
Spickzettel
Method Chaining (Methodenverkettung) ist eine Technik, bei der Methoden den Empfänger (typischerweise *StructType) zurückgeben, was es ermöglicht, mehrere Methodenaufrufe in einer einzigen Anweisung miteinander zu verknüpfen.
Jede Methode muss einen Pointer-Receiver verwenden und *StructType zurückgeben:
type Query struct {
table string
columns []string
where string
limit int
}
func (q *Query) Select(cols ...string) *Query {
q.columns = cols
return q
}
func (q *Query) From(table string) *Query {
q.table = table
return q
}
func (q *Query) Where(condition string) *Query {
q.where = condition
return q
}
func (q *Query) Limit(n int) *Query {
q.limit = n
return q
}Methodenaufrufe flüssig verketten:
query := &Query{}
query.Select("name", "email").From("users").Where("active = true").Limit(10)Method Chaining funktioniert am besten, wenn Operationen ein Objekt konfigurieren oder modifizieren, ohne andere Werte zurückgeben zu müssen. Es wird häufig in Query-Buildern, Konfigurations-APIs und Test-Assertion-Bibliotheken verwendet.
Probier es selbst
package main
import (
"bufio"
"fmt"
"os"
"strconv"
)
func main() {
scanner := bufio.NewScanner(os.Stdin)
// Tag-Namen lesen
scanner.Scan()
tagName := scanner.Text()
// Anzahl der Operationen lesen
scanner.Scan()
numOps, _ := strconv.Atoi(scanner.Text())
// Das Element erstellen
element := NewElement(tagName)
// Jede Operation verarbeiten
for i := 0; i < numOps; i++ {
scanner.Scan()
operation := scanner.Text()
// TODO: Basierend auf dem Operationstyp die entsprechende Methode verketten
// Operationen können sein: "id", "class", "attr" oder "content"
// - Für "id": Lies die nächste Zeile als ID-Wert
// - Für "class": Lies die nächste Zeile als Class-Wert
// - Für "attr": Lies die nächsten ZWEI Zeilen (Attributname, dann Wert)
// - Für "content": Lies die nächste Zeile als Inhaltstext
// Verwende Method Chaining, um das Element flüssig aufzubauen
_ = operation // Entferne diese Zeile bei der Implementierung
}
// Das gerenderte HTML ausgeben
fmt.Println(element.Render())
}
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-Parser3Zeiger & 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 Pool12Fortgeschrittene OOP-Konzepte
Functional Options PatternBuilder-Pattern in GoMethodenverkettungTyp-Aliase vs. DefinitionenReflection-GrundlagenÜberblick zur Code-Generierung