Search with Interfaces
Part of the Object Oriented Programming section of Coddy's GO journey — lesson 101 of 107.
Challenge
EasyLet's add flexible search capabilities to our Library Management System! You'll implement the Strategy pattern using interfaces, allowing users to search for books by different criteria without modifying the core library code.
You'll organize your code across five files:
book.go: YourBookstruct from previous lessons withID,Title,Author,ISBN, andAvailablefields. Include theNewBookconstructor.user.go: YourUserstruct withID,Name,Email, andBorrowedBooksfields. Include theNewUserconstructor.search.go: Define your search strategy interface and implementations.Create a
SearchStrategyinterface with a single method:Match(book *Book, query string) boolImplement three search strategies:
TitleSearch— matches if the book's title contains the query (case-insensitive)AuthorSearch— matches if the book's author contains the query (case-insensitive)ISBNSearch— matches if the book's ISBN exactly equals the query
library.go: YourLibrarystruct with maps for books and users. Add aSearchmethod that accepts anySearchStrategyand a query string, returning a slice of matching book pointers. The method should iterate through all books and use the strategy'sMatchmethod to find results.main.go: Build a library with books, then perform searches using different strategies.Read the number of books, then for each book read its ID, title, author, and ISBN. Next, read the number of search operations. Each operation consists of a search type (
title,author, orisbn) followed by the query string.For each search, print
Search by [type]: [query]followed by the matching book IDs on the next line, separated by commas. If no books match, printNo resultsinstead.
The following inputs will be provided:
- Number of books, then each book's ID, title, author, ISBN (each on separate lines)
- Number of searches, then each search type and query (each on separate lines)
For example, given:
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-1449355739Your output should be:
Search by title: go
B001,B002
Search by author: kennedy
B002
Search by isbn: 978-1449355739
B003And given:
2
B001
Clean Code
Robert Martin
978-0132350884
B002
The Pragmatic Programmer
David Thomas
978-0135957059
2
title
java
author
martinYour output should be:
Search by title: java
No results
Search by author: martin
B001And given:
2
B001
Design Patterns
Gang of Four
978-0201633610
B002
Head First Design Patterns
Eric Freeman
978-0596007126
1
title
designYour output should be:
Search by title: design
B001,B002Notice how the Search method works with any strategy—it doesn't know whether it's searching by title, author, or ISBN. This polymorphic approach means you can add new search types (like searching by availability or publication year) simply by creating new structs that implement SearchStrategy!
Try it yourself
package main
import (
"bufio"
"fmt"
"os"
"strconv"
"strings"
)
func main() {
reader := bufio.NewReader(os.Stdin)
// Read number of books
numBooksStr, _ := reader.ReadString('\n')
numBooks, _ := strconv.Atoi(strings.TrimSpace(numBooksStr))
// Create library
library := NewLibrary()
// Read each book's details
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)
}
// Read number of searches
numSearchesStr, _ := reader.ReadString('\n')
numSearches, _ := strconv.Atoi(strings.TrimSpace(numSearchesStr))
// Process each search
for i := 0; i < numSearches; i++ {
searchType, _ := reader.ReadString('\n')
searchType = strings.TrimSpace(searchType)
query, _ := reader.ReadString('\n')
query = strings.TrimSpace(query)
// TODO: Select the appropriate search strategy based on searchType
// searchType can be "title", "author", or "isbn"
var strategy SearchStrategy
// TODO: Implement strategy selection logic here
// TODO: Perform the search using library.Search(strategy, query)
// TODO: Print the results in the required format
// Format: "Search by [type]: [query]" followed by matching IDs or "No results"
fmt.Printf("Search by %s: %s\n", searchType, query)
// TODO: Print matching book IDs separated by commas, or "No results"
_ = strategy // Remove this line when you implement the solution
}
}
All lessons in Object Oriented Programming
1Fundamentals of Go OOP
External FilesGo Workspace & ModulesPackages & ImportsExported vs Unexported NamesIntroduction to OOP in GoStructs as ClassesDefining Methods on StructsPointer vs Value ReceiversStruct InitializationConstructor FunctionsRecap - Simple Calculator4Interfaces
Introduction to InterfacesImplicit ImplementationInterface as ContractEmpty Interface (any)Type AssertionType SwitchInterface CompositionStringer & Error InterfacesRecap - Shape Calculator7Encapsulation
Exported vs Unexported FieldsPackage-Level EncapsulationGetter & Setter MethodsInformation Hiding in GoRecap - Student Records10Generics (Go 1.18+)
Introduction to GenericsType ParametersType ConstraintsGeneric StructsGeneric Methods WorkaroundRecap - Generic Collection2Types & Structs Deep Dive
Basic & Composite TypesCustom Type DefinitionsStruct TagsAnonymous StructsNested StructsZero Values & DefaultsRecap - Contact Book5Composition Over Inheritance
Why Go Has No InheritanceStruct Embedding BasicsMethod PromotionEmbedding Multiple StructsEmbedding vs AggregationShadowing Embedded MethodsRecap - Employee Hierarchy8Error Handling & OOP
The error InterfaceCustom Error TypesError Wrapping (fmt.Errorf)Sentinel Errorserrors.Is() and errors.As()Panic, Defer, and RecoverRecap - File Parser3Pointers & Memory
Pointer Basics in GoPointers to StructsPass by Value vs ReferenceThe new() FunctionGarbage Collection in GoRecap - Linked List Builder6Polymorphism in Go
Polymorphism via InterfacesDuck Typing in GoInterface Satisfaction RulesPolymorphic CollectionsDependency InjectionRecap - Payment Processor9Concurrency & OOP
Goroutines BasicsChannels & CommunicationBuffered vs Unbuffered ChanSelect Statementsync.Mutex & sync.RWMutexsync.WaitGroupThread-Safe Struct DesignRecap - Worker Pool12Advanced OOP Concepts
Functional Options PatternBuilder Pattern in GoMethod ChainingType Aliases vs DefinitionsReflection BasicsCode Generation Overview15Project: Library Management
Project Overview & StructureBook and User Structs