Sistema de empréstimos
Parte da seção Programação Orientada a Objetos do Journey de GO da Coddy. Lição 100 de 107.
Desafio
FácilVamos construir o sistema de empréstimos para nosso projeto de gerenciamento de Library! Você criará uma struct Library que gerencia coleções de livros e usuários, com métodos para lidar com operações de retirada e devolução: tudo isso com a validação adequada.
Você organizará seu código em quatro arquivos:
book.go: Sua structBookda lição anterior, com os camposID,Title,Author,ISBNeAvailable. Inclua o construtorNewBook, que inicializa os livros como disponíveis.user.go: Sua structUser, comID,Name,EmaileBorrowedBooks(slice de IDs de livros). Inclua o construtorNewUser, que inicializa os usuários com uma lista de empréstimos vazia.library.go: Crie uma structLibraryque armazena livros e usuários em mapas (indexados por seus IDs). Crie estes componentes:- Um construtor
NewLibraryque inicializa mapas vazios para livros e usuários - Um método
AddBookque adiciona um livro à biblioteca - Um método
AddUserque adiciona um usuário à biblioteca - Um método
Borrowque recebe um ID de usuário e um ID de livro, valida a operação, marca o livro como indisponível, adiciona o ID do livro à lista de empréstimos do usuário e retorna um erro se algo der errado - Um método
Returnque reverte o processo de empréstimo: marca o livro como disponível e o remove da lista de empréstimos do usuário
Seu método
Borrowdeve retornar estes erros:user not foundse o ID do usuário não existirbook not foundse o ID do livro não existirbook not availablese o livro já estiver emprestado
Seu método
Returndeve retornar estes erros:user not foundse o ID do usuário não existirbook not foundse o ID do livro não existirbook not borrowedse o livro já estiver disponível
- Um construtor
main.go: Reúna tudo criando uma biblioteca, adicionando livros e usuários e, em seguida, processando operações de empréstimo e devolução.Leia o número de livros e, depois, para cada livro, leia seu ID, título, autor e ISBN. Em seguida, leia o número de usuários e, para cada usuário, leia seu ID, nome e e-mail. Depois, leia o número de operações, em que cada operação é
borrow [userID] [bookID]oureturn [userID] [bookID].Para cada operação, exiba
OKse for bem-sucedida ouError: [message]se falhar.
As seguintes entradas serão fornecidas:
- Número de livros, seguido pelo ID, título, autor e ISBN de cada livro (cada um em uma linha separada)
- Número de usuários, seguido pelo ID, nome e e-mail de cada usuário (cada um em uma linha separada)
- Número de operações, seguido por cada operação em uma linha separada
Por exemplo, dada a entrada:
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 B001Sua saída deve ser:
OK
Error: book not available
OK
Error: user not foundE dada a entrada:
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 B100Sua saída deve ser:
OK
Error: book not available
OKE dada a entrada:
1
B001
Go in Action
William Kennedy
978-1617291784
1
U001
Dave Miller
dave@test.com
2
return U001 B001
borrow U001 B999Sua saída deve ser:
Error: book not borrowed
Error: book not foundObserve como a Library atua como coordenadora central. Ela valida todas as operações antes de modificar o estado, garantindo que livros e usuários permaneçam sincronizados. O uso de receptores de ponteiro permite que seus métodos modifiquem os dados reais armazenados nos mapas!
Experimente você mesmo
package main
import (
"bufio"
"fmt"
"os"
"strings"
)
func main() {
reader := bufio.NewReader(os.Stdin)
// Ler o número de livros
var numBooks int
fmt.Fscanln(reader, &numBooks)
// TODO: Criar uma nova biblioteca
// TODO: Ler os detalhes de cada livro (ID, Title, Author, ISBN em linhas separadas)
// e adicioná-los à biblioteca
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: Criar livro e adicionar à biblioteca
}
// Ler o número de usuários
var numUsers int
fmt.Fscanln(reader, &numUsers)
// TODO: Ler os detalhes de cada usuário (ID, Name, Email em linhas separadas)
// e adicioná-los à biblioteca
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: Criar usuário e adicionar à biblioteca
}
// Ler o número de operações
var numOps int
fmt.Fscanln(reader, &numOps)
// TODO: Processar cada operação
// Formato: "borrow [userID] [bookID]" ou "return [userID] [bookID]"
for i := 0; i < numOps; i++ {
line, _ := reader.ReadString('\n')
line = strings.TrimSpace(line)
parts := strings.Split(line, " ")
// TODO: Analisar a operação e chamar o método apropriado
// Imprima "OK" em caso de sucesso ou "Error: [message]" em caso de falha
}
}
Todas as lições de Programação Orientada a Objetos
1Fundamentos de OOP em Go
Arquivos ExternosWorkspace e Módulos do GoPacotes e ImportsNomes Exportados vs. Não ExportadosIntrodução à OOP em GoStructs como ClassesDefinindo Métodos em StructsReceptores de Ponteiro vs. de ValorInicialização de StructsFunções ConstrutorasRecapitulação — Calculadora Simples4Interfaces
Introdução às InterfacesImplementação ImplícitaInterface como ContratoInterface Vazia (any)Asserção de TipoSwitch de TipoComposição de InterfacesInterfaces Stringer e ErrorRecapitulação - Calculadora de Formas7Encapsulamento
Campos Exportados vs. Não ExportadosEncapsulamento no Nível de PacoteMétodos Getters e SettersOcultação de Informações em GoRecapitulação - Registros de Alunos10Genéricos (Go 1.18+)
Introdução aos genéricosParâmetros de tipoRestrições de tipoStructs genéricasAlternativa para métodos genéricosRecapitulação - Coleção genérica13Padrões de Projeto — Parte 1
Introdução aos Padrões de ProjetoPadrão SingletonPadrão FactoryPadrão Abstract FactoryPadrão ObserverPadrão Strategy2Tipos e Structs em Profundidade
Tipos Básicos e CompostosDefinições de Tipos PersonalizadosTags de StructStructs AnônimasStructs AninhadasValores Zero e PadrõesRecapitulação - Livro de Contatos5Composição em vez de herança
Por que Go não tem herançaNoções básicas de incorporação de structsPromoção de métodosIncorporação de várias structsIncorporação vs agregaçãoOcultação de métodos incorporadosRecapitulação - Hierarquia de funcionários8Tratamento de Erros e OOP
A interface errorTipos de Erro PersonalizadosEncapsulamento de Erros (fmt.Errorf)Erros Sentinelaerrors.Is() e errors.As()Panic, Defer e RecoverRecapitulação - Analisador de Arquivos3Ponteiros e Memória
Fundamentos de Ponteiros em GoPonteiros para StructsPassagem por Valor vs. ReferênciaA Função new()Coleta de Lixo em GoRecapitulação - Construtor de Lista Ligada6Polimorfismo em Go
Polimorfismo via InterfacesDuck Typing em GoRegras de Satisfação de InterfacesColeções PolimórficasInjeção de DependênciasRecapitulação - Processador de Pagamentos9Concorrência e OOP
Fundamentos de GoroutinesCanais e comunicaçãoCanais com e sem bufferInstrução selectsync.Mutex e sync.RWMutexsync.WaitGroupDesign de structs thread-safeRevisão - Worker Pool12Conceitos Avançados de OOP
Padrão de Opções FuncionaisPadrão Builder em GoEncadeamento de MétodosAliases de Tipos vs. DefiniçõesNoções Básicas de ReflectionVisão Geral da Geração de Código15Projeto: Gerenciamento de Biblioteca
Visão geral e estrutura do projetoStructs de livros e usuáriosPratique por conta própria: Compilador de Go online