Busca com interfaces
Parte da seção Programação Orientada a Objetos do Journey de GO da Coddy. Lição 101 de 107.
Desafio
FácilVamos adicionar recursos flexíveis de pesquisa ao nosso Sistema de Gerenciamento de Biblioteca! Você implementará o padrão Strategy usando interfaces, permitindo que os usuários pesquisem livros por diferentes critérios sem modificar o código principal da biblioteca.
Você organizará seu código em cinco arquivos:
book.go: sua structBookdas lições anteriores, com os camposID,Title,Author,ISBNeAvailable. Inclua o construtorNewBook.user.go: sua structUser, com os camposID,Name,EmaileBorrowedBooks. Inclua o construtorNewUser.search.go: defina sua interface de estratégia de pesquisa e suas implementações.Crie uma interface
SearchStrategycom um único método:Match(book *Book, query string) boolImplemente três estratégias de pesquisa:
TitleSearch: corresponde quando o título do livro contém a consulta (sem distinção entre maiúsculas e minúsculas)AuthorSearch: corresponde quando o autor do livro contém a consulta (sem distinção entre maiúsculas e minúsculas)ISBNSearch: corresponde quando o ISBN do livro é exatamente igual à consulta
library.go: sua structLibrary, com mapas para livros e usuários. Adicione um métodoSearchque aceite qualquerSearchStrategye uma string de consulta, retornando um slice de ponteiros para os livros correspondentes. O método deve iterar por todos os livros e usar o métodoMatchda estratégia para encontrar os resultados.main.go: crie uma biblioteca com livros e, em seguida, execute pesquisas usando diferentes estratégias.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 operações de pesquisa. Cada operação consiste em um tipo de pesquisa (
title,authorouisbn) seguido pela string de consulta.Para cada pesquisa, imprima
Search by [type]: [query]e, na linha seguinte, os IDs dos livros correspondentes, ordenados em ordem crescente e separados por vírgulas (um mapa é percorrido em ordem aleatória, portanto, ordene os IDs antes de imprimi-los). Se nenhum livro corresponder, imprimaNo results.
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 pesquisas, seguido pelo tipo e pela consulta de cada pesquisa (cada um em uma linha separada)
Por exemplo, dadas as entradas:
3
B001
The Go Programming Language
Alan Donovan
978-0134190440
B002
Go in Action
William Kennedy
978-1617291784
B003
Learning Python
Mark Lutz
978-1449355739
3
title
go
author
kennedy
isbn
978-1449355739Sua saída deverá ser:
Search by title: go
B001,B002
Search by author: kennedy
B002
Search by isbn: 978-1449355739
B003E dadas as entradas:
2
B001
Clean Code
Robert Martin
978-0132350884
B002
The Pragmatic Programmer
David Thomas
978-0135957059
2
title
java
author
martinSua saída deverá ser:
Search by title: java
No results
Search by author: martin
B001E dadas as entradas:
2
B001
Design Patterns
Gang of Four
978-0201633610
B002
Head First Design Patterns
Eric Freeman
978-0596007126
1
title
designSua saída deverá ser:
Search by title: design
B001,B002Observe como o método Search funciona com qualquer estratégia. Ele não sabe se está pesquisando por título, autor ou ISBN. Essa abordagem polimórfica significa que você pode adicionar novos tipos de pesquisa (como pesquisar por disponibilidade ou ano de publicação) simplesmente criando novas structs que implementem SearchStrategy!
Experimente você mesmo
package main
import (
"bufio"
"fmt"
"os"
"strconv"
"strings"
)
func main() {
reader := bufio.NewReader(os.Stdin)
// Ler o número de livros
numBooksStr, _ := reader.ReadString('\n')
numBooks, _ := strconv.Atoi(strings.TrimSpace(numBooksStr))
// Criar a biblioteca
library := NewLibrary()
// Ler os detalhes de cada livro
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)
book := NewBook(id, title, author, isbn)
library.AddBook(book)
}
// Ler o número de buscas
numSearchesStr, _ := reader.ReadString('\n')
numSearches, _ := strconv.Atoi(strings.TrimSpace(numSearchesStr))
// Processar cada busca
for i := 0; i < numSearches; i++ {
searchType, _ := reader.ReadString('\n')
searchType = strings.TrimSpace(searchType)
query, _ := reader.ReadString('\n')
query = strings.TrimSpace(query)
// TODO: Selecione a estratégia de busca apropriada com base em searchType
// searchType pode ser "title", "author" ou "isbn"
var strategy SearchStrategy
// TODO: Implemente a lógica de seleção de estratégia aqui
// TODO: Realize a busca usando library.Search(strategy, query)
// TODO: Imprima os resultados no formato exigido
// Formato: "Search by [type]: [query]" seguido pelos IDs correspondentes ou "No results"
fmt.Printf("Search by %s: %s\n", searchType, query)
// TODO: Imprima os IDs dos livros correspondentes separados por vírgulas, ou "No results"
_ = strategy // Remova esta linha quando implementar a solução
}
}
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