Interfaccia CLI per amministratori
Fa parte della sezione Programmazione orientata agli oggetti del percorso GO di Coddy. Lezione 103 di 107.
Sfida
FacileCostruiamo un'interfaccia a riga di comando per il nostro sistema di gestione della biblioteca usando il pattern Command! Creerai una CLI che elabora comandi amministrativi, come aggiungere libri, registrare utenti e gestire le operazioni di prestito, il tutto tramite un'architettura pulita ed estensibile.
Organizzerai il codice in sei file:
book.go: la tua structBookcon tag JSON perID,Title,Author,ISBNeAvailable. Includi il costruttoreNewBook.user.go: la tua structUsercon tag JSON perID,Name,EmaileBorrowedBooks. Includi il costruttoreNewUser.library.go: la tua structLibrarycon mappe per libri e utenti, insieme ai metodiAddBook,AddUser,BorroweReturndelle lezioni precedenti.commands.go: è qui che il pattern Command prende vita! Definisci un'interfacciaCommandcon un metodoExecuteche accetta un*Librarye argomenti[]string, restituendo una stringa come risultato. Poi implementa queste struct per i comandi:AddBookCommand: si aspetta 4 argomenti: id, title, author, isbn. Aggiunge il libro e restituisceBook added: [title]AddUserCommand: si aspetta 3 argomenti: id, name, email. Aggiunge l'utente e restituisceUser added: [name]BorrowCommand: si aspetta 2 argomenti: userID, bookID. In caso di successo restituisceBorrowed: [bookID], altrimentiError: [message]ReturnCommand: si aspetta 2 argomenti: userID, bookID. In caso di successo restituisceReturned: [bookID], altrimentiError: [message]ListBooksCommand: non accetta argomenti. Restituisce l'ID e il titolo di ogni libro su righe separate nel formato[id]: [title], oppureNo booksse l'elenco è vuoto (ordina i libri per ID)
Se un comando riceve un numero insufficiente di argomenti, restituisci
Error: insufficient argumentscli.go: crea una structCLIche contiene un puntatore a unaLibrarye una mappa di nomi di comandi associati alle implementazioni diCommand. Realizza:- Il costruttore
NewCLI, che inizializza la CLI con una biblioteca e registra tutti i comandi:addbook,adduser,borrow,return,listbooks - Il metodo
Run, che accetta una stringa di input, la analizza usandostrings.Fields, cerca il comando e lo esegue. RestituisceNo command providedse l'input è vuoto, oppureUnknown command: [name]per i comandi non riconosciuti
- Il costruttore
main.go: crea una biblioteca e una CLI, poi elabora i comandi ricevuti in input. Leggi il numero di comandi, quindi leggi ogni stringa di comando su una riga separata. Per ogni comando, chiamaRune stampa il risultato.
Verranno forniti i seguenti input:
- Numero di comandi
- Ogni comando come stringa completa su una riga propria
Per esempio, dato:
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 B001L'output dovrebbe essere:
Book added: Go-Programming
Book added: Clean-Code
User added: Alice
Borrowed: B001
B001: Go-Programming
B002: Clean-Code
Error: book not availableE dato:
4
listbooks
addbook B100 Design-Patterns Gang-of-Four 978-0201633610
listbooks
invalidcmd testL'output dovrebbe essere:
No books
Book added: Design-Patterns
B100: Design-Patterns
Unknown command: invalidcmdE dato:
5
adduser U001 Bob bob@email.com
borrow U001 B001
addbook B001 Golang-Guide John-Smith 123-456
borrow U001 B001
return U001 B001L'output dovrebbe essere:
User added: Bob
Error: book not found
Book added: Golang-Guide
Borrowed: B001
Returned: B001Nota che la CLI non deve conoscere i dettagli di ogni operazione. Si limita a cercare il comando e a delegarne l'esecuzione. In questo modo, aggiungere nuovi comandi è semplice come creare una nuova struct che implementa l'interfaccia Command e registrarla nella CLI!
Provalo tu
package main
import (
"bufio"
"fmt"
"os"
)
func main() {
// Leggi il numero di comandi
var n int
fmt.Scanln(&n)
// Crea uno scanner per leggere righe intere
scanner := bufio.NewScanner(os.Stdin)
// TODO: Crea una nuova Library
// TODO: Crea una nuova CLI con la libreria
// TODO: Elabora ogni comando
// Per ciascuno degli n comandi:
// - Leggi la riga del comando usando scanner.Scan() e scanner.Text()
// - Esegui il comando tramite la CLI
// - Stampa il risultato
_ = scanner // Rimuovi questa riga quando usi scanner
}
Tutte le lezioni di Programmazione orientata agli oggetti
1Fondamenti di OOP in Go
File esterniWorkspace e moduli GoPacchetti e importazioniNomi esportati e non esportatiIntroduzione all’OOP in GoGli struct come classiDefinire metodi sugli structReceiver con puntatore vs receiver con valoreInizializzazione degli structFunzioni costruttriciRiepilogo - Calcolatrice semplice4Interfacce
Introduzione alle interfacceImplementazione implicitaL’interfaccia come contrattoInterfaccia vuota (any)Asserzione di tipoSwitch sul tipoComposizione di interfacceInterfacce Stringer ed ErrorRipasso - Calcolatore di forme7Incapsulamento
Campi esportati e non esportatiIncapsulamento a livello di packageMetodi Getter e SetterNascondimento delle informazioni in GoRiepilogo - Registri degli studenti10Tipi generici (Go 1.18+)
Introduzione ai tipi genericiParametri di tipoVincoli di tipoStruct genericheSoluzione alternativa per i metodi genericiRiepilogo - Collezione generica13Modelli di progettazione Parte 1
Introduzione ai modelli di progettazioneModello SingletonModello FactoryModello Abstract FactoryModello ObserverModello Strategy2Approfondimento su tipi e struct
Tipi di base e compostiDefinizioni di tipi personalizzatiTag delle structStruct anonimeStruct annidateValori zero e predefinitiRipasso - Rubrica5Composizione invece dell'ereditarietà
Perché Go non ha l'ereditarietàFondamenti dell'embedding delle structPromozione dei metodiEmbedding di più structEmbedding e aggregazione a confrontoMascheramento dei metodi embeddedRiepilogo: gerarchia dei dipendenti8Gestione degli errori e OOP
L'interfaccia errorTipi di errore personalizzatiWrapping degli errori (fmt.Errorf)Errori sentinellaerrors.Is() ed errors.As()Panic, Defer e RecoverRiepilogo - Parser di file11Libreria standard e OOP
io.Reader e io.Writersort.InterfaceInterfaccia fmt.Stringerencoding/json con le structInterfaccia http.HandlerRipasso - modelli REST API14Modelli di progettazione – Parte 2
Pattern CommandPattern AdapterPattern DecoratorPattern Template MethodPattern StatePattern CompositeMiddleware come Decorator3Puntatori e memoria
Concetti base dei puntatori in GoPuntatori a structPassaggio per valore vs per riferimentoLa funzione new()Garbage collection in GoRiepilogo - Costruttore di liste concatenate6Polimorfismo in Go
Polimorfismo tramite interfacceDuck typing in GoRegole di soddisfacimento delle interfacceCollezioni polimorficheIniezione delle dipendenzeRiepilogo - Elaboratore di pagamenti9Concorrenza e OOP
Basi delle goroutineCanali e comunicazioneCanali bufferizzati vs non bufferizzatiIstruzione selectsync.Mutex e sync.RWMutexsync.WaitGroupProgettazione di struct thread-safeRiepilogo: worker pool12Concetti avanzati di OOP
Pattern delle opzioni funzionaliPattern Builder in GoConcatenamento dei metodiAlias di tipo e definizioni a confrontoNozioni di base sulla reflectionPanoramica sulla generazione del codice15Progetto: Gestione della biblioteca
Panoramica e struttura del progettoStruct per libri e utentiEsercitati da solo: Compilatore Go online