Admin-CLI-Oberfläche
Teil des Abschnitts Objektorientierte Programmierung der GO-Journey von Coddy. Lektion 103 von 107.
Aufgabe
EinfachErstellen wir eine Befehlszeilenschnittstelle für unser Bibliotheksverwaltungssystem mithilfe des Befehlsmusters! Du erstellst eine CLI, die Admin-Befehle wie das Hinzufügen von Büchern, das Registrieren von Benutzern und die Verwaltung von Ausleihvorgängen verarbeitet – und das alles durch eine saubere, erweiterbare Architektur.
Du organisierst deinen Code über sechs Dateien:
book.go: DeineBook-Struktur mit JSON-Tags fürID,Title,Author,ISBNundAvailable. Füge denNewBook-Konstruktor hinzu.user.go: DeineUser-Struktur mit JSON-Tags fürID,Name,EmailundBorrowedBooks. Füge denNewUser-Konstruktor hinzu.library.go: DeineLibrary-Struktur mit Maps für Bücher und Benutzer sowie den MethodenAddBook,AddUser,BorrowundReturnaus den vorherigen Lektionen.commands.go: Hier wird das Befehlsmuster zum Leben erweckt! Definiere einCommand-Interface mit einerExecute-Methode, die einen*Library-Wert und[]string-Argumente entgegennimmt und ein String-Ergebnis zurückgibt. Implementiere anschließend diese Befehlsstrukturen:AddBookCommand: erwartet 4 Argumente: id, title, author, isbn. Fügt das Buch hinzu und gibtBook added: [title]zurück.AddUserCommand: erwartet 3 Argumente: id, name, email. Fügt den Benutzer hinzu und gibtUser added: [name]zurück.BorrowCommand: erwartet 2 Argumente: userID, bookID. Gibt bei ErfolgBorrowed: [bookID]oder bei einem FehlerError: [message]zurück.ReturnCommand: erwartet 2 Argumente: userID, bookID. Gibt bei ErfolgReturned: [bookID]oder bei einem FehlerError: [message]zurück.ListBooksCommand: benötigt keine Argumente. Gibt die ID und den Titel jedes Buchs in separaten Zeilen im Format[id]: [title]zurück oderNo books, wenn keine Bücher vorhanden sind (Bücher nach ID sortieren).
Wenn ein Befehl nicht genügend Argumente erhält, gib
Error: insufficient argumentszurück.cli.go: Erstelle eineCLI-Struktur, die einen Zeiger auf eineLibraryund eine Map mit Befehlsnamen undCommand-Implementierungen enthält. Erstelle:- den
NewCLI-Konstruktor, der die CLI mit einer Bibliothek initialisiert und alle Befehle registriert:addbook,adduser,borrow,return,listbooks - die
Run-Methode, die einen Eingabestring entgegennimmt, ihn mithilfe vonstrings.Fieldsanalysiert, den Befehl sucht und ihn ausführt. Gib bei leerer EingabeNo command providedoder bei unbekannten BefehlenUnknown command: [name]zurück.
- den
main.go: Erstelle eine Bibliothek und eine CLI und verarbeite anschließend Befehle aus der Eingabe. Lies die Anzahl der Befehle ein und anschließend jeden Befehlsstring in einer eigenen Zeile. Rufe für jeden BefehlRunauf und gib das Ergebnis aus.
Die folgenden Eingaben werden bereitgestellt:
- Anzahl der Befehle
- Jeder Befehl als vollständiger String in einer eigenen Zeile
Beispiel für folgende Eingabe:
6
addbook B001 Go-Programming Alan-Donovan 978-0134190440
addbook B002 Clean-Code Robert-Martin 978-0132350884
adduser U001 Alice alice@test.com
borrow U001 B001
listbooks
borrow U001 B001Deine Ausgabe sollte folgendermaßen aussehen:
Book added: Go-Programming
Book added: Clean-Code
User added: Alice
Borrowed: B001
B001: Go-Programming
B002: Clean-Code
Error: book not availableUnd bei folgender Eingabe:
4
listbooks
addbook B100 Design-Patterns Gang-of-Four 978-0201633610
listbooks
invalidcmd testDeine Ausgabe sollte folgendermaßen aussehen:
No books
Book added: Design-Patterns
B100: Design-Patterns
Unknown command: invalidcmdUnd bei folgender Eingabe:
5
adduser U001 Bob bob@email.com
borrow U001 B001
addbook B001 Golang-Guide John-Smith 123-456
borrow U001 B001
return U001 B001Deine Ausgabe sollte folgendermaßen aussehen:
User added: Bob
Error: book not found
Book added: Golang-Guide
Borrowed: B001
Returned: B001Beachte, dass die CLI die Details der einzelnen Vorgänge nicht kennen muss. Sie sucht einfach den Befehl und delegiert die Ausführung. Dadurch ist das Hinzufügen neuer Befehle so einfach wie das Erstellen einer neuen Struktur, die das Command-Interface implementiert, und deren Registrierung in der CLI!
Probier es selbst
package main
import (
"bufio"
"fmt"
"os"
)
func main() {
// Lese die Anzahl der Befehle
var n int
fmt.Scanln(&n)
// Erstelle einen Scanner, um vollständige Zeilen zu lesen
scanner := bufio.NewScanner(os.Stdin)
// TODO: Erstelle eine neue Library
// TODO: Erstelle eine neue CLI mit der Library
// TODO: Verarbeite jeden Befehl
// Für jeden der n Befehle:
// - Lese die Befehlszeile mit scanner.Scan() und scanner.Text()
// - Führe den Befehl über die CLI aus
// - Gib das Ergebnis aus
_ = scanner // Entferne diese Zeile, wenn du scanner verwendest
}
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