Ausleihsystem
Teil des Abschnitts Objektorientierte Programmierung der GO-Journey von Coddy. Lektion 100 von 107.
Aufgabe
EinfachErstellen wir das Ausleihsystem für unser Bibliotheksverwaltungsprojekt! Du erstellst eine Library-Struktur, die Sammlungen von books und Benutzern verwaltet, mit Methoden zur Verarbeitung von Ausleih- und Rückgabevorgängen: einschließlich einer ordnungsgemäßen Validierung.
Du organisierst deinen Code über vier Dateien:
book.go: DeineBook-Struktur aus der vorherigen Lektion mit den FeldernID,Title,Author,ISBNundAvailable. Füge denNewBook-Konstruktor hinzu, der books als verfügbar initialisiert.user.go: DeineUser-Struktur mitID,Name,EmailundBorrowedBooks(Slice von Buch-IDs). Füge denNewUser-Konstruktor hinzu, der Benutzer mit einer leeren Ausleihliste initialisiert.library.go: Erstelle eineLibrary-Struktur, die books und Benutzer in Maps speichert (geordnet nach ihren IDs). Erstelle diese Komponenten:- Ein
NewLibrary-Konstruktor, der leere Maps für books 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 bei einem Fehler einen Fehler zurückgibt - Eine
Return-Methode, die den Ausleihvorgang rückgängig macht: Sie markiert das Buch als verfügbar und entfernt es aus der Ausleihliste des Benutzers
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
- Ein
main.go: Führe alles zusammen, indem du eine Bibliothek erstellst, books und Benutzer hinzufügst und anschließend Ausleih- und Rückgabevorgänge verarbeitest.Lies die Anzahl der books und anschließend für jedes Buch seine ID, seinen Titel, seinen Autor und seine ISBN ein. Lies danach die Anzahl der Benutzer und für jeden Benutzer seine ID, seinen Namen und seine E-Mail-Adresse ein. Lies anschließend die Anzahl der Vorgänge ein, wobei jeder Vorgang entweder
borrow [userID] [bookID]oderreturn [userID] [bookID]ist.Gib für jeden Vorgang entweder
OKaus, wenn er erfolgreich war, oderError: [message], wenn er fehlschlägt.
Die folgenden Eingaben werden bereitgestellt:
- Anzahl der books, anschließend die ID, der Titel, der Autor und die ISBN jedes Buchs (jeweils in einer eigenen Zeile)
- Anzahl der Benutzer, anschließend die ID, der Name und die E-Mail-Adresse jedes Benutzers (jeweils in einer eigenen Zeile)
- Anzahl der Vorgänge, anschließend jeder Vorgang in einer eigenen Zeile
Zum Beispiel bei folgender Eingabe:
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 folgendermaßen aussehen:
OK
Error: book not available
OK
Error: user not foundUnd bei folgender Eingabe:
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 folgendermaßen aussehen:
OK
Error: book not available
OKUnd bei folgender Eingabe:
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 folgendermaßen aussehen:
Error: book not borrowed
Error: book not foundBeachte, wie die Library als zentrale Koordinatorin fungiert. Sie validiert alle Vorgänge, bevor sie den Zustand verändert, und stellt so sicher, dass books und Benutzer synchron bleiben. Durch die Verwendung von Pointer-Receivern können deine Methoden die tatsächlichen in den Maps gespeicherten Daten verä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.Fscanln(reader, &numBooks)
// TODO: Eine neue Bibliothek erstellen
// TODO: Details jedes Buches lesen (ID, Title, Author, ISBN in separaten Zeilen)
// und sie zur 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.Fscanln(reader, &numUsers)
// TODO: Details jedes Benutzers lesen (ID, Name, Email in separaten Zeilen)
// und sie zur 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.Fscanln(reader, &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
// Gib "OK" bei Erfolg oder "Error: [message]" bei Fehlschlag aus
}
}
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