Suche mit Interfaces
Teil des Abschnitts Objektorientierte Programmierung der GO-Journey von Coddy. Lektion 101 von 107.
Aufgabe
EinfachFügen wir unserem Bibliotheksverwaltungssystem flexible Suchfunktionen hinzu! Du wirst das Strategy-Muster mithilfe von Interfaces implementieren, sodass Benutzer nach Büchern anhand verschiedener Kriterien suchen können, ohne den Kerncode der Bibliothek zu verändern.
Du wirst deinen Code auf fünf Dateien aufteilen:
book.go: DeineBook-Struktur aus den vorherigen Lektionen mit den FeldernID,Title,Author,ISBNundAvailable. Füge den KonstruktorNewBookhinzu.user.go: DeineUser-Struktur mit den FeldernID,Name,EmailundBorrowedBooks. Füge den KonstruktorNewUserhinzu.search.go: Definiere dein Suchstrategie-Interface und die Implementierungen.Erstelle ein
SearchStrategy-Interface mit einer einzigen Methode:Match(book *Book, query string) boolImplementiere drei Suchstrategien:
TitleSearch: stimmt überein, wenn der Titel des Buches die Suchanfrage enthält (ohne Beachtung der Groß- und Kleinschreibung)AuthorSearch: stimmt überein, wenn der Autor des Buches die Suchanfrage enthält (ohne Beachtung der Groß- und Kleinschreibung)ISBNSearch: stimmt überein, wenn die ISBN des Buches genau der Suchanfrage entspricht
library.go: DeineLibrary-Struktur mit Maps für Bücher und Benutzer. Füge eineSearch-Methode hinzu, die jede beliebigeSearchStrategyund eine Suchanfrage akzeptiert und ein Slice mit Zeigern auf die passenden Bücher zurückgibt. Die Methode soll alle Bücher durchlaufen und dieMatch-Methode der Strategie verwenden, um Ergebnisse zu finden.main.go: Erstelle eine Bibliothek mit Büchern und führe anschließend Suchen mit verschiedenen Strategien durch.Lies die Anzahl der Bücher ein und anschließend für jedes Buch seine ID, seinen Titel, seinen Autor und seine ISBN. Lies danach die Anzahl der Suchvorgänge ein. Jeder Vorgang besteht aus einem Suchtyp (
title,authoroderisbn), gefolgt von der Suchanfrage.Gib für jede Suche
Search by [type]: [query]aus, gefolgt von den IDs der passenden Bücher in der nächsten Zeile, aufsteigend sortiert und durch Kommas getrennt (eine Map wird in zufälliger Reihenfolge durchlaufen, daher müssen die IDs vor der Ausgabe sortiert werden). Wenn keine Bücher übereinstimmen, gib stattdessenNo resultsaus.
Die folgenden Eingaben werden bereitgestellt:
- Anzahl der Bücher, danach die ID, der Titel, der Autor und die ISBN jedes Buches (jeweils in einer eigenen Zeile)
- Anzahl der Suchen, danach jeweils der Suchtyp und die Suchanfrage (jeweils in einer eigenen Zeile)
Zum Beispiel bei folgender Eingabe:
3
B001
The Go Programming Language
Alan Donovan
978-0134190440
B002
Go in Action
William Kennedy
978-1617291784
B003
Learning Python
Mark Lutz
978-1449355739
3
title
go
author
kennedy
isbn
978-1449355739sollte deine Ausgabe folgendermaßen aussehen:
Search by title: go
B001,B002
Search by author: kennedy
B002
Search by isbn: 978-1449355739
B003Und bei folgender Eingabe:
2
B001
Clean Code
Robert Martin
978-0132350884
B002
The Pragmatic Programmer
David Thomas
978-0135957059
2
title
java
author
martinsollte deine Ausgabe folgendermaßen aussehen:
Search by title: java
No results
Search by author: martin
B001Und bei folgender Eingabe:
2
B001
Design Patterns
Gang of Four
978-0201633610
B002
Head First Design Patterns
Eric Freeman
978-0596007126
1
title
designsollte deine Ausgabe folgendermaßen aussehen:
Search by title: design
B001,B002Beachte, wie die Search-Methode mit jeder Strategie funktioniert. Sie weiß nicht, ob sie nach Titel, Autor oder ISBN sucht. Dieser polymorphe Ansatz bedeutet, dass du neue Suchtypen (wie die Suche nach Verfügbarkeit oder Erscheinungsjahr) einfach hinzufügen kannst, indem du neue Strukturen erstellst, die SearchStrategy implementieren!
Probier es selbst
package main
import (
"bufio"
"fmt"
"os"
"strconv"
"strings"
)
func main() {
reader := bufio.NewReader(os.Stdin)
// Anzahl der Bücher lesen
numBooksStr, _ := reader.ReadString('\n')
numBooks, _ := strconv.Atoi(strings.TrimSpace(numBooksStr))
// Bibliothek erstellen
library := NewLibrary()
// Details jedes Buches lesen
for i := 0; i < numBooks; i++ {
id, _ := reader.ReadString('\n')
id = strings.TrimSpace(id)
title, _ := reader.ReadString('\n')
title = strings.TrimSpace(title)
author, _ := reader.ReadString('\n')
author = strings.TrimSpace(author)
isbn, _ := reader.ReadString('\n')
isbn = strings.TrimSpace(isbn)
book := NewBook(id, title, author, isbn)
library.AddBook(book)
}
// Anzahl der Suchen lesen
numSearchesStr, _ := reader.ReadString('\n')
numSearches, _ := strconv.Atoi(strings.TrimSpace(numSearchesStr))
// Jede Suche verarbeiten
for i := 0; i < numSearches; i++ {
searchType, _ := reader.ReadString('\n')
searchType = strings.TrimSpace(searchType)
query, _ := reader.ReadString('\n')
query = strings.TrimSpace(query)
// TODO: Wähle die passende Suchstrategie basierend auf searchType
// searchType kann "title", "author" oder "isbn" sein
var strategy SearchStrategy
// TODO: Implementiere hier die Logik zur Strategiewahl
// TODO: Führe die Suche mit library.Search(strategy, query) durch
// TODO: Gib die Ergebnisse im erforderlichen Format aus
// Format: "Search by [type]: [query]" gefolgt von übereinstimmenden IDs oder "No results"
fmt.Printf("Search by %s: %s\n", searchType, query)
// TODO: Gib übereinstimmende Buch-IDs durch Kommas getrennt aus, oder "No results"
_ = strategy // Entferne diese Zeile, wenn du die Lösung implementierst
}
}
Alle Lektionen in Objektorientierte Programmierung
1Grundlagen der OOP in Go
Externe DateienGo-Workspace & ModulePackages & ImportsExportierte vs. nicht exportierte NamenEinführung in OOP mit GoStructs als KlassenMethoden für Structs definierenPointer- vs. Value-ReceiverStruct-InitialisierungKonstruktorfunktionenRückblick – Einfacher Taschenrechner4Schnittstellen
Einführung in SchnittstellenImplizite ImplementierungSchnittstelle als VertragLeere Schnittstelle (any)TypzusicherungTypwechselZusammensetzung von SchnittstellenStringer- und Error-SchnittstellenRückblick – Formenrechner7Kapselung
Exportierte vs. nicht exportierte FelderKapselung auf PaketebeneGetter- und Setter-MethodenInformationsverbergung in GoRückblick – Studierendendatensätze10Generics (Go 1.18+)
Einführung in GenericsTypparameterTypbeschränkungenGenerische StrukturenWorkaround für generische MethodenZusammenfassung – Generische Sammlung2Typen & Structs im Detail
Grundlegende & zusammengesetzte TypenBenutzerdefinierte TypdefinitionenStruct-TagsAnonyme StructsVerschachtelte StructsNullwerte & StandardwerteRückblick – Kontaktbuch5Komposition statt Vererbung
Warum Go keine Vererbung hatGrundlagen der Struct-EinbettungMethoden-PromotionMehrere Structs einbettenEinbettung vs. AggregationVerbergen eingebetteter MethodenRückblick – Mitarbeiterhierarchie8Fehlerbehandlung & OOP
Das Error-InterfaceBenutzerdefinierte FehlertypenError-Wrapping (fmt.Errorf)Sentinel-Fehlererrors.Is() und errors.As()Panic, Defer und RecoverRückblick – Dateiparser3Zeiger & Speicher
Grundlagen von Zeigern in GoZeiger auf StructsÜbergabe per Wert vs. ReferenzDie Funktion new()Garbage Collection in GoRückblick – Verkettete Liste erstellen6Polymorphismus in Go
Polymorphismus über InterfacesDuck-Typing in GoRegeln zur Interface-ErfüllungPolymorphe SammlungenDependency InjectionZusammenfassung – Zahlungsprozessor9Konkurrenz & OOP
Grundlagen der GoroutinesChannels & KommunikationGepufferte vs. ungepufferte ChannelsSelect-Anweisungsync.Mutex & sync.RWMutexsync.WaitGroupThread-sicheres Struct-DesignRückblick – Worker Pool12Fortgeschrittene OOP-Konzepte
Functional-Options-PatternBuilder-Pattern in GoMethod ChainingTyp-Aliase vs. DefinitionenGrundlagen der ReflectionÜberblick über Codegenerierung15Projekt: Bibliotheksverwaltung
Projektübersicht & StrukturBuch- und Benutzer-StructsÜbe selbstständig: Online-Go-Compiler