Búsqueda con interfaces
Parte de la sección Programación Orientada a Objetos del Journey de GO de Coddy — lección 101 de 107.
Desafío
Fácil¡Vamos a añadir capacidades de búsqueda flexibles a nuestro Sistema de Gestión de Bibliotecas! Implementarás el patrón Strategy utilizando interfaces, lo que permitirá a los usuarios buscar libros por diferentes criterios sin modificar el código principal de la biblioteca.
Organizarás tu código en cinco archivos:
book.go: Tu estructuraBookde lecciones anteriores con los camposID,Title,Author,ISBNyAvailable. Incluye el constructorNewBook.user.go: Tu estructuraUsercon los camposID,Name,EmailyBorrowedBooks. Incluye el constructorNewUser.search.go: Define tu interfaz de estrategia de búsqueda e implementaciones.Crea una interfaz
SearchStrategycon un único método:Match(book *Book, query string) boolImplementa tres estrategias de búsqueda:
TitleSearch— coincide si el título del libro contiene la consulta (sin distinguir entre mayúsculas y minúsculas)AuthorSearch— coincide si el autor del libro contiene la consulta (sin distinguir entre mayúsculas y minúsculas)ISBNSearch— coincide si el ISBN del libro es exactamente igual a la consulta
library.go: Tu estructuraLibrarycon mapas para libros y usuarios. Añade un métodoSearchque acepte cualquierSearchStrategyy una cadena de consulta, devolviendo un slice de punteros a libros coincidentes. El método debe iterar a través de todos los libros y utilizar el métodoMatchde la estrategia para encontrar resultados.main.go: Construye una biblioteca con libros, luego realiza búsquedas utilizando diferentes estrategias.Lee el número de libros, luego para cada libro lee su ID, título, autor e ISBN. A continuación, lee el número de operaciones de búsqueda. Cada operación consiste en un tipo de búsqueda (
title,authoroisbn) seguido de la cadena de consulta.Para cada búsqueda, imprime
Search by [type]: [query]seguido de los IDs de los libros coincidentes en la siguiente línea, separados por comas. Si no hay libros que coincidan, imprimeNo resultsen su lugar.
Se proporcionarán las siguientes entradas:
- Número de libros, luego el ID, título, autor e ISBN de cada libro (cada uno en líneas separadas)
- Número de búsquedas, luego cada tipo de búsqueda y consulta (cada uno en líneas separadas)
Por ejemplo, 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-1449355739Tu salida debería ser:
Search by title: go
B001,B002
Search by author: kennedy
B002
Search by isbn: 978-1449355739
B003Y dado:
2
B001
Clean Code
Robert Martin
978-0132350884
B002
The Pragmatic Programmer
David Thomas
978-0135957059
2
title
java
author
martinTu salida debería ser:
Search by title: java
No results
Search by author: martin
B001Y dado:
2
B001
Design Patterns
Gang of Four
978-0201633610
B002
Head First Design Patterns
Eric Freeman
978-0596007126
1
title
designTu salida debería ser:
Search by title: design
B001,B002Observa cómo el método Search funciona con cualquier estrategia; no sabe si está buscando por título, autor o ISBN. ¡Este enfoque polimórfico significa que puedes añadir nuevos tipos de búsqueda (como buscar por disponibilidad o año de publicación) simplemente creando nuevas estructuras que implementen SearchStrategy!
Pruébalo tú mismo
package main
import (
"bufio"
"fmt"
"os"
"strconv"
"strings"
)
func main() {
reader := bufio.NewReader(os.Stdin)
// Leer el número de libros
numBooksStr, _ := reader.ReadString('\n')
numBooks, _ := strconv.Atoi(strings.TrimSpace(numBooksStr))
// Crear biblioteca
library := NewLibrary()
// Leer los detalles de cada libro
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)
}
// Leer el número de búsquedas
numSearchesStr, _ := reader.ReadString('\n')
numSearches, _ := strconv.Atoi(strings.TrimSpace(numSearchesStr))
// Procesar cada búsqueda
for i := 0; i < numSearches; i++ {
searchType, _ := reader.ReadString('\n')
searchType = strings.TrimSpace(searchType)
query, _ := reader.ReadString('\n')
query = strings.TrimSpace(query)
// TODO: Seleccionar la estrategia de búsqueda adecuada basada en searchType
// searchType puede ser "title", "author" o "isbn"
var strategy SearchStrategy
// TODO: Implementar la lógica de selección de estrategia aquí
// TODO: Realizar la búsqueda usando library.Search(strategy, query)
// TODO: Imprimir los resultados en el formato requerido
// Formato: "Search by [type]: [query]" seguido de los IDs coincidentes o "No results"
fmt.Printf("Search by %s: %s\n", searchType, query)
// TODO: Imprimir los IDs de los libros coincidentes separados por comas, o "No results"
_ = strategy // Elimina esta línea cuando implementes la solución
}
}
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