Wyszukiwanie z użyciem interfejsów
Część sekcji Programowanie obiektowe ścieżki GO w Coddy. Lekcja 101 z 107.
Wyzwanie
ŁatwyDodajmy elastyczne możliwości wyszukiwania do naszego systemu zarządzania biblioteką! Zaimplementujesz wzorzec Strategia przy użyciu interfejsów, umożliwiając użytkownikom wyszukiwanie książek według różnych kryteriów bez modyfikowania podstawowego kodu biblioteki.
Rozmieścisz swój kod w pięciu plikach:
book.go: Twoja strukturaBookz poprzednich lekcji, zawierająca polaID,Title,Author,ISBNiAvailable. Uwzględnij konstruktorNewBook.user.go: Twoja strukturaUserz polamiID,Name,EmailiBorrowedBooks. Uwzględnij konstruktorNewUser.search.go: Zdefiniuj interfejs strategii wyszukiwania i jego implementacje.Utwórz interfejs
SearchStrategyz jedną metodą:Match(book *Book, query string) boolZaimplementuj trzy strategie wyszukiwania:
TitleSearch: dopasowuje książkę, jeśli jej tytuł zawiera zapytanie (bez rozróżniania wielkości liter)AuthorSearch: dopasowuje książkę, jeśli nazwisko autora zawiera zapytanie (bez rozróżniania wielkości liter)ISBNSearch: dopasowuje książkę, jeśli jej ISBN jest dokładnie taki sam jak zapytanie
library.go: Twoja strukturaLibraryz mapami książek i użytkowników. Dodaj metodęSearch, która przyjmuje dowolną strategięSearchStrategyoraz ciąg zapytania i zwraca wycinek wskaźników do dopasowanych książek. Metoda powinna przejść przez wszystkie książki i użyć metodyMatchstrategii, aby znaleźć wyniki.main.go: Utwórz bibliotekę z książkami, a następnie wyszukuj przy użyciu różnych strategii.Odczytaj liczbę książek, a następnie dla każdej książki odczytaj jej ID, tytuł, autora i ISBN. Następnie odczytaj liczbę operacji wyszukiwania. Każda operacja składa się z typu wyszukiwania (
title,authorlubisbn), po którym następuje ciąg zapytania.Dla każdego wyszukiwania wypisz
Search by [type]: [query], a w następnym wierszu identyfikatory pasujących książek, posortowane rosnąco i rozdzielone przecinkami (elementy mapy są iterowane w losowej kolejności, dlatego przed wypisaniem posortuj identyfikatory). Jeśli żadna książka nie pasuje, wypiszNo results.
Dane wejściowe będą miały następujący format:
- Liczba książek, a następnie ID, tytuł, autor i ISBN każdej książki (każdy element w osobnym wierszu)
- Liczba wyszukiwań, a następnie typ i zapytanie dla każdego wyszukiwania (każdy element w osobnym wierszu)
Na przykład dla danych:
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-1449355739Wynik powinien być następujący:
Search by title: go
B001,B002
Search by author: kennedy
B002
Search by isbn: 978-1449355739
B003A dla danych:
2
B001
Clean Code
Robert Martin
978-0132350884
B002
The Pragmatic Programmer
David Thomas
978-0135957059
2
title
java
author
martinWynik powinien być następujący:
Search by title: java
No results
Search by author: martin
B001A dla danych:
2
B001
Design Patterns
Gang of Four
978-0201633610
B002
Head First Design Patterns
Eric Freeman
978-0596007126
1
title
designWynik powinien być następujący:
Search by title: design
B001,B002Zwróć uwagę, że metoda Search działa z dowolną strategią. Nie wie, czy wyszukiwanie odbywa się według tytułu, autora czy ISBN. Dzięki temu polimorficznemu podejściu możesz dodawać nowe typy wyszukiwania (na przykład według dostępności lub roku publikacji), po prostu tworząc nowe struktury implementujące SearchStrategy!
Spróbuj swoich sił
package main
import (
"bufio"
"fmt"
"os"
"strconv"
"strings"
)
func main() {
reader := bufio.NewReader(os.Stdin)
// Wczytaj liczbę książek
numBooksStr, _ := reader.ReadString('\n')
numBooks, _ := strconv.Atoi(strings.TrimSpace(numBooksStr))
// Utwórz bibliotekę
library := NewLibrary()
// Wczytaj dane każdej książki
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)
}
// Wczytaj liczbę wyszukiwań
numSearchesStr, _ := reader.ReadString('\n')
numSearches, _ := strconv.Atoi(strings.TrimSpace(numSearchesStr))
// Przetwórz każde wyszukiwanie
for i := 0; i < numSearches; i++ {
searchType, _ := reader.ReadString('\n')
searchType = strings.TrimSpace(searchType)
query, _ := reader.ReadString('\n')
query = strings.TrimSpace(query)
// TODO: Wybierz odpowiednią strategię wyszukiwania na podstawie searchType
// searchType może mieć wartość "title", "author" lub "isbn"
var strategy SearchStrategy
// TODO: Zaimplementuj tutaj logikę wyboru strategii
// TODO: Wykonaj wyszukiwanie za pomocą library.Search(strategy, query)
// TODO: Wyświetl wyniki w wymaganym formacie
// Format: "Search by [type]: [query]", a następnie pasujące identyfikatory ID lub "No results"
fmt.Printf("Search by %s: %s\n", searchType, query)
// TODO: Wyświetl identyfikatory ID pasujących książek oddzielone przecinkami lub "No results"
_ = strategy // Usuń tę linię, gdy zaimplementujesz rozwiązanie
}
}
Wszystkie lekcje w sekcji Programowanie obiektowe
1Podstawy OOP w Go
Pliki zewnętrzneObszar roboczy i moduły GoPakiety i importyNazwy eksportowane i nieeksportowaneWprowadzenie do OOP w GoStruktury jako klasyDefiniowanie metod dla strukturOdbiorniki wskaźnikowe i wartościoweInicjalizacja strukturFunkcje konstruktoraPodsumowanie – prosty kalkulator4Interfejsy
Wprowadzenie do interfejsówImplementacja niejawnaInterfejs jako kontraktPusty interfejs (any)Asercja typuPrzełącznik typówKompozycja interfejsówInterfejsy Stringer i ErrorPowtórka — kalkulator figur7Hermetyzacja
Pola eksportowane i nieeksportowaneHermetyzacja na poziomie pakietuMetody pobierające i ustawiająceUkrywanie informacji w GoPowtórka – dane studentów10Typy generyczne (Go 1.18+)
Wprowadzenie do typów generycznychParametry typówOgraniczenia typówStruktury generyczneObejście ograniczeń metod generycznychPodsumowanie — generyczna kolekcja2Typy i struktury w praktyce
Typy proste i złożoneDefiniowanie własnych typówTagi pól strukturStruktury anonimoweStruktury zagnieżdżoneWartości zerowe i domyślnePodsumowanie – książka kontaktów5Kompozycja zamiast dziedziczenia
Dlaczego Go nie ma dziedziczeniaPodstawy osadzania strukturPromowanie metodOsadzanie wielu strukturOsadzanie a agregacjaPrzesłanianie osadzonych metodPodsumowanie — hierarchia pracowników8Obsługa błędów i programowanie obiektowe
Interfejs błęduWłasne typy błędówOpakowywanie błędów (fmt.Errorf)Błędy wartowniczeerrors.Is() i errors.As()Panic, Defer i RecoverPodsumowanie — parser plików3Wskaźniki i pamięć
Podstawy wskaźników w GoWskaźniki do strukturPrzekazywanie przez wartość a przez referencjęFunkcja new()Odśmiecanie pamięci w GoPowtórka — kreator listy wiązanej6Polimorfizm w Go
Polimorfizm za pomocą interfejsówDuck typing w GoZasady spełniania interfejsówKolekcje polimorficzneWstrzykiwanie zależnościPowtórka — procesor płatności9Współbieżność i OOP
Podstawy goroutinesKanały i komunikacjaKanały buforowane i niebuforowaneInstrukcja selectsync.Mutex i sync.RWMutexsync.WaitGroupProjektowanie struktur bezpiecznych wątkowoPowtórka – pula workerów12Zaawansowane zagadnienia programowania obiektowego
Wzorzec opcji funkcyjnychWzorzec Builder w GoŁańcuchowe wywoływanie metodAliasy typów a definicje typówPodstawy refleksjiPrzegląd generowania kodu15Projekt: Zarządzanie biblioteką
Przegląd i struktura projektuStruktury książek i użytkownikówPoćwicz samodzielnie: Kompilator Go online