Interface CLI de Administrador
Parte da seção Programação Orientada a Objetos do Journey de GO da Coddy — lição 103 de 107.
Desafio
FácilVamos construir uma interface de linha de comando para o nosso Sistema de Gerenciamento de Biblioteca usando o Command Pattern! Você criará uma CLI que processa comandos de administrador, como adicionar livros, registrar usuários e gerenciar operações de empréstimo — tudo por meio de uma arquitetura limpa e extensível.
Você organizará seu código em seis arquivos:
book.go: Sua structBookcom tags JSON paraID,Title,Author,ISBNeAvailable. Inclua o construtorNewBook.user.go: Sua structUsercom tags JSON paraID,Name,EmaileBorrowedBooks. Inclua o construtorNewUser.library.go: Sua structLibrarycom mapas para livros e usuários, juntamente com os métodosAddBook,AddUser,BorroweReturndas lições anteriores.commands.go: É aqui que o Command Pattern ganha vida! Defina uma interfaceCommandcom um métodoExecuteque recebe um*Librarye argumentos[]string, retornando um resultado string. Em seguida, implemente estas structs de comando:AddBookCommand— espera 4 argumentos: id, title, author, isbn. Adiciona o livro e retorna"Book added: " + book.TitleAddUserCommand— espera 3 argumentos: id, name, email. Adiciona o usuário e retorna"User added: " + user.NameBorrowCommand— espera 2 argumentos: userID, bookID. Retorna"Borrowed: " + args[1]em caso de sucesso, ou"Error: " + err.Error()em caso de falhaReturnCommand— espera 2 argumentos: userID, bookID. Retorna"Returned: " + args[1]em caso de sucesso, ou"Error: " + err.Error()em caso de falhaListBooksCommand— não recebe argumentos. Retorna o ID e o título de cada livro em linhas separadas no formato[id]: [title], ou"No books"se estiver vazio (liste os livros ordenados por ID)
Se um comando receber argumentos insuficientes, retorne
"Error: insufficient arguments"cli.go: Crie uma structCLIque contém um ponteiro para umaLibrarye um mapa de nomes de comandos para implementações deCommand. Construa:- Construtor
NewCLIque inicializa a CLI com uma biblioteca e registra todos os comandos:"addbook","adduser","borrow","return","listbooks" - Método
Runque recebe uma string de entrada, analisa-a usandostrings.Fields, procura o comando e o executa. Retorne"No command provided"para entrada vazia, ou"Unknown command: " + parts[0]para comandos não reconhecidos
- Construtor
main.go: Crie uma biblioteca e uma CLI, depois processe os comandos da entrada. Leia o número de comandos e, em seguida, leia cada string de comando em uma linha separada. Para cada comando, chameRune imprima o resultado.
As seguintes entradas serão fornecidas:
- Número de comandos
- Cada comando como uma string completa em sua própria linha
Por exemplo, 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 B001Sua saída deve ser:
Book added: Go-Programming
Book added: Clean-Code
User added: Alice
Borrowed: B001
B001: Go-Programming
B002: Clean-Code
Error: book not availableE dado:
4
listbooks
addbook B100 Design-Patterns Gang-of-Four 978-0201633610
listbooks
invalidcmd testSua saída deve ser:
No books
Book added: Design-Patterns
B100: Design-Patterns
Unknown command: invalidcmdE dado:
5
adduser U001 Bob bob@email.com
borrow U001 B001
addbook B001 Golang-Guide John-Smith 123-456
borrow U001 B001
return U001 B001Sua saída deve ser:
User added: Bob
Error: book not found
Book added: Golang-Guide
Borrowed: B001
Returned: B001Observe como a CLI não precisa conhecer os detalhes de cada operação — ela simplesmente procura o comando e delega a execução. Isso torna a adição de novos comandos tão simples quanto criar uma nova struct que implementa a interface Command e registrá-la na CLI!
Experimente você mesmo
package main
import (
"bufio"
"fmt"
"os"
)
func main() {
// Lê o número de comandos
var n int
fmt.Scanln(&n)
// Cria um scanner para ler linhas completas
scanner := bufio.NewScanner(os.Stdin)
// TODO: Cria uma nova Library
// TODO: Cria uma nova CLI com a biblioteca
// TODO: Processa cada comando
// Para cada um dos n comandos:
// - Lê a linha de comando usando scanner.Scan() e scanner.Text()
// - Executa o comando através da CLI
// - Imprime o resultado
_ = scanner // Remova esta linha quando você usar o scanner
}
Todas as lições de Programação Orientada a Objetos
1Fundamentos de OOP em Go
Arquivos ExternosGo Workspace e MódulosPacotes e ImportaçõesNomes Exportados vs Não ExportadosIntrodução a OOP em GoStructs como ClassesDefinindo Métodos em StructsRecebedores de Ponteiro vs ValorInicialização de StructsFunções ConstrutorasRecapitulação - Calculadora Simples4Interfaces
Introdução a InterfacesImplementação ImplícitaInterface como ContratoInterface Vazia (any)Type AssertionType SwitchComposição de InterfacesInterfaces Stringer & ErrorRecapitulação - Calculadora de Formas7Encapsulamento
Campos Exportados vs Não ExportadosEncapsulamento em Nível de PacoteMétodos Getter e SetterOcultação de Informação em GoRecapitulação - Registros de Estudantes10Generics (Go 1.18+)
Introdução a GenericsParâmetros de TipoRestrições de TipoStructs GenéricasSolução Alternativa para Métodos GenéricosRecapitulação - Coleção Genérica2Mergulho Profundo em Tipos e Structs
Tipos Básicos e CompostosDefinições de Tipos PersonalizadosStruct TagsStructs AnônimasStructs AninhadasZero Values e PadrõesRecapitulação - Agenda de Contatos5Composição em vez de Herança
Por que Go não possui HerançaFundamentos de Incorporação de StructsPromoção de MétodosIncorporando Múltiplas StructsIncorporação vs AgregaçãoShadowing de Métodos IncorporadosRecapitulação - Hierarquia de Funcionários8Tratamento de Erros e OOP
A Interface errorTipos de Erro PersonalizadosError Wrapping (fmt.Errorf)Erros Sentinelaerrors.Is() e errors.As()Panic, Defer e RecoverRecapitulação - File Parser3Ponteiros e Memória
Fundamentos de Ponteiros em GoPonteiros para StructsPassagem por Valor vs ReferênciaA Função new()Garbage Collection em GoRecapitulação - Construtor de Lista Encadeada6Polimorfismo em Go
Polimorfismo via InterfacesDuck Typing em GoRegras de Satisfação de InterfaceColeções PolimórficasInjeção de DependênciaRecapitulação - Processador de Pagamentos9Concorrência e OOP
Fundamentos de GoroutinesCanais e ComunicaçãoCanais com Buffer vs. Sem BufferInstrução Selectsync.Mutex e sync.RWMutexsync.WaitGroupDesign de Structs Thread-SafeRecapitulação - Worker Pool12Conceitos Avançados de OOP
Padrão Functional OptionsPadrão Builder em GoEncadeamento de MétodosType Aliases vs DefiniçõesFundamentos de ReflectionVisão Geral de Geração de Código15Projeto: Gerenciamento de Biblioteca
Visão Geral e Estrutura do ProjetoStructs de Livro e Usuário