Ausleihsystem
Teil des Abschnitts Objektorientierte Programmierung der GO-Journey von Coddy — Lektion 100 von 107.
Aufgabe
EinfachLass uns das Ausleihsystem für unser Bibliotheksverwaltungsprojekt bauen! Du wirst eine Library-Struktur erstellen, die Sammlungen von Büchern und Benutzern verwaltet, mit Methoden zur Abwicklung von Ausleih- und Rückgabevorgängen – inklusive ordnungsgemäßer Validierung.
Du wirst deinen Code auf vier Dateien verteilen:
book.go: DeineBook-Struktur aus der vorherigen Lektion mit den FeldernID,Title,Author,ISBNundAvailable. Füge denNewBook-Konstruktor hinzu, der Bücher als verfügbar initialisiert.user.go: DeineUser-Struktur mitID,Name,EmailundBorrowedBooks(ein Slice von Buch-IDs). Füge denNewUser-Konstruktor hinzu, der Benutzer mit einer leeren Ausleihliste initialisiert.library.go: Erstelle eineLibrary-Struktur, die Bücher und Benutzer in Maps speichert (mit ihren IDs als Schlüssel). Baue diese Komponenten:- Einen
NewLibrary-Konstruktor, der leere Maps für Bücher und Benutzer initialisiert - Eine
AddBook-Methode, die ein Buch zur Bibliothek hinzufügt - Eine
AddUser-Methode, die einen Benutzer zur Bibliothek hinzufügt - Eine
Borrow-Methode, die eine Benutzer-ID und eine Buch-ID entgegennimmt, den Vorgang validiert, das Buch als nicht verfügbar markiert, die Buch-ID zur Ausleihliste des Benutzers hinzufügt und einen Fehler zurückgibt, falls etwas schiefgeht - Eine
Return-Methode, die den Ausleihvorgang umkehrt – das Buch als verfügbar markiert und es aus der Ausleihliste des Benutzers entfernt
Deine
Borrow-Methode sollte diese Fehler zurückgeben:user not found, wenn die Benutzer-ID nicht existiertbook not found, wenn die Buch-ID nicht existiertbook not available, wenn das Buch bereits ausgeliehen ist
Deine
Return-Methode sollte diese Fehler zurückgeben:user not found, wenn die Benutzer-ID nicht existiertbook not found, wenn die Buch-ID nicht existiertbook not borrowed, wenn das Buch bereits verfügbar ist
- Einen
main.go: Führe alles zusammen, indem du eine Bibliothek erstellst, Bücher und Benutzer hinzufügst und dann Ausleih-/Rückgabevorgänge verarbeitest.Lies die Anzahl der Bücher ein, dann für jedes Buch seine ID, den Titel, den Autor und die ISBN. Lies als Nächstes die Anzahl der Benutzer ein und für jeden Benutzer seine ID, den Namen und die E-Mail. Lies dann die Anzahl der Operationen ein, wobei jede Operation entweder
borrow [userID] [bookID]oderreturn [userID] [bookID]ist.Gib für jede Operation entweder
OKbei Erfolg oderError: [message]bei einem Fehler aus.
Die folgenden Eingaben werden bereitgestellt:
- Anzahl der Bücher, dann die ID, der Titel, der Autor und die ISBN jedes Buches (jeweils in separaten Zeilen)
- Anzahl der Benutzer, dann die ID, der Name und die E-Mail jedes Benutzers (jeweils in separaten Zeilen)
- Anzahl der Operationen, dann jede Operation in einer separaten Zeile
Zum Beispiel, gegeben:
2
B001
The Go Programming Language
Alan Donovan
978-0134190440
B002
Clean Code
Robert Martin
978-0132350884
1
U001
Alice Smith
alice@library.com
4
borrow U001 B001
borrow U001 B001
return U001 B001
borrow U002 B001Deine Ausgabe sollte sein:
OK
Error: book not available
OK
Error: user not foundUnd gegeben:
1
B100
Design Patterns
Gang of Four
978-0201633610
2
U001
Bob Jones
bob@email.com
U002
Carol White
carol@email.com
3
borrow U001 B100
borrow U002 B100
return U001 B100Deine Ausgabe sollte sein:
OK
Error: book not available
OKUnd gegeben:
1
B001
Go in Action
William Kennedy
978-1617291784
1
U001
Dave Miller
dave@test.com
2
return U001 B001
borrow U001 B999Deine Ausgabe sollte sein:
Error: book not borrowed
Error: book not foundBeachte, wie die Library als zentraler Koordinator fungiert – sie validiert alle Operationen, bevor sie den Zustand ändert, und stellt sicher, dass Bücher und Benutzer synchron bleiben. Die Verwendung von Pointer-Receivern ermöglicht es deinen Methoden, die tatsächlich in den Maps gespeicherten Daten zu ändern!
Probier es selbst
package main
import (
"bufio"
"fmt"
"os"
"strings"
)
func main() {
reader := bufio.NewReader(os.Stdin)
// Anzahl der Bücher lesen
var numBooks int
fmt.Scanln(&numBooks)
// TODO: Eine neue Bibliothek erstellen
// TODO: Details jedes Buches lesen (ID, Title, Author, ISBN in separaten Zeilen)
// und sie der Bibliothek hinzufügen
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)
// TODO: Buch erstellen und zur Bibliothek hinzufügen
}
// Anzahl der Benutzer lesen
var numUsers int
fmt.Scanln(&numUsers)
// TODO: Details jedes Benutzers lesen (ID, Name, Email in separaten Zeilen)
// und sie der Bibliothek hinzufügen
for i := 0; i < numUsers; i++ {
id, _ := reader.ReadString('\n')
id = strings.TrimSpace(id)
name, _ := reader.ReadString('\n')
name = strings.TrimSpace(name)
email, _ := reader.ReadString('\n')
email = strings.TrimSpace(email)
// TODO: Benutzer erstellen und zur Bibliothek hinzufügen
}
// Anzahl der Operationen lesen
var numOps int
fmt.Scanln(&numOps)
// TODO: Jede Operation verarbeiten
// Format: "borrow [userID] [bookID]" oder "return [userID] [bookID]"
for i := 0; i < numOps; i++ {
line, _ := reader.ReadString('\n')
line = strings.TrimSpace(line)
parts := strings.Split(line, " ")
// TODO: Die Operation parsen und die entsprechende Methode aufrufen
// Gibt "OK" bei Erfolg oder "Error: [message]" bei Fehler aus
}
}
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-Generierung15Projekt: Bibliotheksverwaltung
Projektübersicht & StrukturBuch- und Benutzer-Structs