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 capacidades de busca flexíveis ao nosso Sistema de Gerenciamento de Biblioteca! Você implementará o padrão Strategy usando interfaces, permitindo que os usuários busquem 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 structUsercom os camposID,Name,EmaileBorrowedBooks. Inclua o construtorNewUser.search.go: Defina sua interface de estratégia de busca e as implementações.Crie uma interface
SearchStrategycom um único método:Match(book *Book, query string) boolImplemente três estratégias de busca:
TitleSearch— corresponde se o título do livro contém a query (insensível a maiúsculas e minúsculas)AuthorSearch— corresponde se o autor do livro contém a query (insensível a maiúsculas e minúsculas)ISBNSearch— corresponde se o ISBN do livro é exatamente igual à query
library.go: Sua structLibrarycom mapas para livros e usuários. Adicione um métodoSearchque aceita qualquerSearchStrategye uma string de consulta (query), retornando um slice de ponteiros de livros correspondentes. O método deve iterar por todos os livros e usar o métodoMatchda estratégia para encontrar os resultados.main.go: Construa uma biblioteca com livros e, em seguida, realize buscas usando diferentes estratégias.Leia o número de livros e, para cada livro, leia seu ID, título, autor e ISBN. Em seguida, leia o número de operações de busca. Cada operação consiste em um tipo de busca (
title,authorouisbn) seguido pela string de consulta.Para cada busca, imprima
Search by [type]: [query]seguido pelos IDs dos livros correspondentes na próxima linha, separados por vírgulas. Se nenhum livro corresponder, imprimaNo resultsem vez disso.
As seguintes entradas serão fornecidas:
- Número de livros, depois o ID, título, autor e ISBN de cada livro (cada um em linhas separadas)
- Número de buscas, depois cada tipo de busca e consulta (cada um em linhas separadas)
Por exemplo, dado:
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 deve ser:
Search by title: go
B001,B002
Search by author: kennedy
B002
Search by isbn: 978-1449355739
B003E dado:
2
B001
Clean Code
Robert Martin
978-0132350884
B002
The Pragmatic Programmer
David Thomas
978-0135957059
2
title
java
author
martinSua saída deve ser:
Search by title: java
No results
Search by author: martin
B001E dado:
2
B001
Design Patterns
Gang of Four
978-0201633610
B002
Head First Design Patterns
Eric Freeman
978-0596007126
1
title
designSua saída deve ser:
Search by title: design
B001,B002Observe como o método Search funciona com qualquer estratégia — ele não sabe se está buscando por título, autor ou ISBN. Essa abordagem polimórfica significa que você pode adicionar novos tipos de busca (como busca por disponibilidade ou ano de publicação) simplesmente criando novas structs que implementam SearchStrategy!
Experimente você mesmo
package main
import (
"bufio"
"fmt"
"os"
"strconv"
"strings"
)
func main() {
reader := bufio.NewReader(os.Stdin)
// Lê o número de livros
numBooksStr, _ := reader.ReadString('\n')
numBooks, _ := strconv.Atoi(strings.TrimSpace(numBooksStr))
// Cria a biblioteca
library := NewLibrary()
// Lê 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)
}
// Lê o número de buscas
numSearchesStr, _ := reader.ReadString('\n')
numSearches, _ := strconv.Atoi(strings.TrimSpace(numSearchesStr))
// Processa 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: Seleciona a estratégia de busca apropriada baseada em searchType
// searchType pode ser "title", "author", ou "isbn"
var strategy SearchStrategy
// TODO: Implementa a lógica de seleção de estratégia aqui
// TODO: Realiza a busca usando library.Search(strategy, query)
// TODO: Imprime 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: Imprime os IDs dos livros correspondentes separados por vírgulas, ou "No results"
_ = strategy // Remova esta linha quando você implementar a solução
}
}
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