Podsumowanie — generyczna kolekcja
Część sekcji Programowanie obiektowe ścieżki GO w Coddy. Lekcja 72 z 107.
Wyzwanie
ŁatwyZbudujmy generyczną strukturę danych Queue, która pokaże wszystko, czego nauczysz się o typach generycznych w Go! W przeciwieństwie do stosu (LIFO), kolejka działa zgodnie z zasadą First-In-First-Out (FIFO): pierwszy dodany element jest pierwszym usuwanym.
Podzielisz kod na dwa pliki:
queue.go: Zdefiniuj generyczną kolekcję kolejki.Utwórz generyczną strukturę
Queue[T any], która przechowuje elementy. Kolejka powinna obsługiwać następujące operacje:Enqueue(item T)— dodaje element na końcu kolejkiDequeue() (T, bool)— usuwa i zwraca element z początku kolejki wraz z wartością logiczną wskazującą powodzenie (zwróć wartość zerową ifalse, jeśli kolejka jest pusta)Peek() (T, bool)— zwraca element z początku kolejki, nie usuwając go (ten sam schemat zwracanych wartości co w przypadku Dequeue)Size() int— zwraca liczbę elementów w kolejceIsEmpty() bool— zwraca true, jeśli kolejka nie zawiera żadnych elementów
Utwórz również funkcję konstruktora
NewQueue[T any]() *Queue[T], która zwraca wskaźnik do zainicjowanej, pustej kolejki.main.go: Zademonstruj działanie kolejki z różnymi typami na podstawie danych wejściowych.Wczytaj wskaźnik typu (
intlubstring), a następnie wczytaj serię poleceń do wykonania na kolejce. Każde polecenie znajduje się w osobnym wierszu:enqueue [value]— dodaje wartość do kolejkidequeue— usuwa i wypisuje element z początku kolejki (wypiszempty, jeśli kolejka jest pusta)peek— wypisuje element z początku kolejki, nie usuwając go (wypiszempty, jeśli kolejka jest pusta)size— wypisuje bieżący rozmiar
Wczytuj polecenia, aż otrzymasz
done.
Dane wejściowe będą miały następującą postać:
- Wiersz 1: Wskaźnik typu (
intlubstring) - Kolejne wiersze: Polecenia aż do
done
Na przykład, dla danych wejściowych:
int
enqueue 10
enqueue 20
enqueue 30
peek
dequeue
size
dequeue
dequeue
dequeue
doneWynik powinien być następujący:
10
10
2
20
30
emptyA dla danych wejściowych:
string
enqueue hello
enqueue world
size
peek
dequeue
peek
doneWynik powinien być następujący:
2
hello
hello
worldKolejka powinna działać identycznie dla typów całkowitych i tekstowych, pokazując, jak jedna generyczna implementacja obsługuje wiele konkretnych typów, zachowując pełne bezpieczeństwo typów.
Spróbuj swoich sił
package main
import (
"bufio"
"fmt"
"os"
"strconv"
"strings"
)
func main() {
scanner := bufio.NewScanner(os.Stdin)
// Odczytaj wskaźnik typu
scanner.Scan()
typeIndicator := scanner.Text()
if typeIndicator == "int" {
// TODO: Utwórz kolejkę liczb całkowitych za pomocą NewQueue[int]()
// Przetwarzaj polecenia dla kolejki liczb całkowitych
for scanner.Scan() {
line := scanner.Text()
if line == "done" {
break
}
parts := strings.SplitN(line, " ", 2)
command := parts[0]
// TODO: Obsłuż polecenia: enqueue, dequeue, peek, size
// Dla enqueue przekształć wartość z parts[1] na liczbę całkowitą
// Dla dequeue/peek wypisz "empty", jeśli kolejka jest pusta
_ = command
}
} else if typeIndicator == "string" {
// TODO: Utwórz kolejkę ciągów znaków za pomocą NewQueue[string]()
// Przetwarzaj polecenia dla kolejki ciągów znaków
for scanner.Scan() {
line := scanner.Text()
if line == "done" {
break
}
parts := strings.SplitN(line, " ", 2)
command := parts[0]
// TODO: Obsłuż polecenia: enqueue, dequeue, peek, size
// Dla enqueue użyj ciągu znaków z parts[1]
// Dla dequeue/peek wypisz "empty", jeśli kolejka jest pusta
_ = command
}
}
// Te instrukcje zapobiegają błędom nieużywanych importów podczas tworzenia programu
_ = strconv.Atoi
_ = fmt.Println
}
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 koduPoćwicz samodzielnie: Kompilator Go online