Interfaz CLI de administración
Parte de la sección Programación Orientada a Objetos del Journey de GO de Coddy — lección 103 de 107.
Desafío
Fácil¡Vamos a construir una interfaz de línea de comandos para nuestro Sistema de Gestión de Biblioteca utilizando el Patrón Command! Crearás una CLI que procesa comandos de administrador como añadir libros, registrar usuarios y gestionar operaciones de préstamo, todo a través de una arquitectura limpia y extensible.
Organizarás tu código en seis archivos:
book.go: Tu structBookcon etiquetas JSON paraID,Title,Author,ISBNyAvailable. Incluye el constructorNewBook.user.go: Tu structUsercon etiquetas JSON paraID,Name,EmailyBorrowedBooks. Incluye el constructorNewUser.library.go: Tu structLibrarycon mapas para libros y usuarios, junto con los métodosAddBook,AddUser,BorrowyReturnde lecciones anteriores.commands.go: ¡Aquí es donde el Patrón Command cobra vida! Define una interfazCommandcon un métodoExecuteque recibe un*Libraryy argumentos[]string, devolviendo un resultado de tipo string. Luego implementa estos structs de comando:AddBookCommand— espera 4 argumentos: id, title, author, isbn. Añade el libro y devuelveBook added: [title]AddUserCommand— espera 3 argumentos: id, name, email. Añade al usuario y devuelveUser added: [name]BorrowCommand— espera 2 argumentos: userID, bookID. DevuelveBorrowed: [bookID]en caso de éxito, oError: [message]en caso de falloReturnCommand— espera 2 argumentos: userID, bookID. DevuelveReturned: [bookID]en caso de éxito, oError: [message]en caso de falloListBooksCommand— no recibe argumentos. Devuelve el ID y el título de cada libro en líneas separadas con el formato[id]: [title], oNo bookssi está vacío (lista los libros ordenados por ID)
Si un comando recibe argumentos insuficientes, devuelve
Error: insufficient argumentscli.go: Crea un structCLIque contenga un puntero a unaLibraryy un mapa de nombres de comandos a implementaciones deCommand. Construye:- El constructor
NewCLIque inicializa la CLI con una biblioteca y registra todos los comandos:addbook,adduser,borrow,return,listbooks - El método
Runque recibe una cadena de entrada, la analiza usandostrings.Fields, busca el comando y lo ejecuta. DevuelveNo command providedpara una entrada vacía, oUnknown command: [name]para comandos no reconocidos
- El constructor
main.go: Crea una biblioteca y una CLI, luego procesa los comandos de la entrada. Lee el número de comandos, luego lee cada cadena de comando en una línea separada. Para cada comando, llama aRune imprime el resultado.
Se proporcionarán las siguientes entradas:
- Número de comandos
- Cada comando como una cadena completa en su propia línea
Por ejemplo, dado:
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 B001Tu salida debería ser:
Book added: Go-Programming
Book added: Clean-Code
User added: Alice
Borrowed: B001
B001: Go-Programming
B002: Clean-Code
Error: book not availableY dado:
4
listbooks
addbook B100 Design-Patterns Gang-of-Four 978-0201633610
listbooks
invalidcmd testTu salida debería ser:
No books
Book added: Design-Patterns
B100: Design-Patterns
Unknown command: invalidcmdY dado:
5
adduser U001 Bob bob@email.com
borrow U001 B001
addbook B001 Golang-Guide John-Smith 123-456
borrow U001 B001
return U001 B001Tu salida debería ser:
User added: Bob
Error: book not found
Book added: Golang-Guide
Borrowed: B001
Returned: B001Observa cómo la CLI no necesita conocer los detalles de cada operación; simplemente busca el comando y delega la ejecución. ¡Esto hace que añadir nuevos comandos sea tan sencillo como crear un nuevo struct que implemente la interfaz Command y registrarlo en la CLI!
Pruébalo tú mismo
package main
import (
"bufio"
"fmt"
"os"
)
func main() {
// Lee el número de comandos
var n int
fmt.Scanln(&n)
// Crea un scanner para leer líneas completas
scanner := bufio.NewScanner(os.Stdin)
// TODO: Crea una nueva Library
// TODO: Crea un nuevo CLI con la biblioteca
// TODO: Procesa cada comando
// Para cada uno de los n comandos:
// - Lee la línea de comando usando scanner.Scan() y scanner.Text()
// - Ejecuta el comando a través del CLI
// - Imprime el resultado
_ = scanner // Elimina esta línea cuando uses scanner
}
Todas las lecciones de Programación Orientada a Objetos
1Fundamentos de POO en Go
Archivos externosEspacio de trabajo y módulos de GoPaquetes e importacionesNombres exportados vs. no exportadosIntroducción a la POO en GoStructs como clasesDefinición de métodos en structsReceptores de puntero vs. de valorInicialización de structsFunciones constructorasResumen - Calculadora simple4Interfaces
Introducción a las interfacesImplementación implícitaLa interfaz como contratoInterfaz vacía (any)Type AssertionType SwitchComposición de interfacesInterfaces Stringer y ErrorResumen: Calculadora de figuras7Encapsulamiento
Campos exportados vs. no exportadosEncapsulamiento a nivel de paqueteMétodos Getter y SetterOcultamiento de información en GoResumen - Registros de estudiantes10Genéricos (Go 1.18+)
Introducción a los GenéricosParámetros de tipoRestricciones de tipoStructs genéricosSolución alternativa para métodos genéricosResumen - Colección genérica13Patrones de diseño - Parte 1
Introducción a los patrones de diseñoPatrón SingletonPatrón FactoryPatrón Abstract FactoryPatrón ObserverPatrón Strategy2Inmersión profunda en Tipos y Structs
Tipos básicos y compuestosDefiniciones de tipos personalizadosEtiquetas de StructsStructs anónimosStructs anidadosValores cero y por defectoRepaso - Libreta de contactos5Composición sobre herencia
Por qué Go no tiene herenciaConceptos básicos de incrustación de structsPromoción de métodosIncrustación de múltiples structsIncrustación vs AgregaciónShadowing de métodos incrustadosResumen - Jerarquía de empleados8Manejo de Errores y OOP
La interfaz errorTipos de errores personalizadosEnvoltura de errores (fmt.Errorf)Errores centinelaerrors.Is() y errors.As()Panic, Defer y RecoverResumen - Analizador de archivos3Punteros y Memoria
Fundamentos de punteros en GoPunteros a StructsPaso por valor vs referenciaLa función new()Garbage Collection en GoResumen - Constructor de Linked List6Polimorfismo en Go
Polimorfismo mediante interfacesDuck Typing en GoReglas de satisfacción de interfacesColecciones polimórficasInyección de dependenciasResumen - Procesador de pagos9Concurrencia y POO
Fundamentos de GoroutinesChannels y comunicaciónChannels con buffer vs. sin bufferSentencia Selectsync.Mutex y sync.RWMutexsync.WaitGroupDiseño de estructuras Thread-SafeResumen - Worker Pool12Conceptos avanzados de POO
Patrón Functional OptionsPatrón Builder en GoEncadenamiento de métodosAlias de tipos vs. definicionesFundamentos de ReflectionDescripción general de generación de código15Proyecto: Gestión de bibliotecas
Descripción general y estructura del proyectoStructs de libros y usuarios