Zusammenfassung – Generische Collection
Teil des Abschnitts Objektorientierte Programmierung der GO-Journey von Coddy — Lektion 72 von 107.
Aufgabe
EinfachLassen Sie uns eine generische Queue-Datenstruktur erstellen, die alles demonstriert, was Sie über Generics in Go gelernt haben! Im Gegensatz zu einem Stack (LIFO) folgt eine Queue dem First-In-First-Out (FIFO)-Prinzip – das erste hinzugefügte Element wird als erstes wieder entfernt.
Sie werden Ihren Code auf zwei Dateien aufteilen:
queue.go: Definieren Sie Ihre generische Queue-Sammlung.Erstellen Sie ein generisches Struct
Queue[T any], das Elemente intern speichert. Ihre Queue sollte diese Operationen unterstützen:Enqueue(item T)- fügt ein Element am Ende der Queue hinzuDequeue() (T, bool)- entfernt das Element am Anfang der Queue und gibt es zurück, zusammen mit einem Boolean, der den Erfolg anzeigt (geben Sie den Nullwert undfalsezurück, wenn die Queue leer ist)Peek() (T, bool)- gibt das vordere Element zurück, ohne es zu entfernen (gleiches Rückgabemuster wie Dequeue)Size() int- gibt die Anzahl der Elemente in der Queue zurückIsEmpty() bool- gibt true zurück, wenn die Queue keine Elemente enthält
Erstellen Sie außerdem eine Konstruktor-Funktion
NewQueue[T any]() *Queue[T], die einen Pointer auf eine initialisierte leere Queue zurückgibt.main.go: Demonstrieren Sie Ihre Queue mit verschiedenen Typen basierend auf der Eingabe.Lesen Sie einen Typ-Indikator (
intoderstring) ein und lesen Sie dann eine Reihe von Befehlen, die auf der Queue ausgeführt werden sollen. Jeder Befehl steht in einer eigenen Zeile:enqueue [value]- fügt den Wert zur Queue hinzudequeue- entfernt das vordere Element und gibt es aus (geben Sieemptyaus, wenn die Queue leer ist)peek- gibt das vordere Element aus, ohne es zu entfernen (geben Sieemptyaus, wenn die Queue leer ist)size- gibt die aktuelle Größe aus
Lesen Sie Befehle ein, bis Sie
doneerhalten.
Die folgenden Eingaben werden bereitgestellt:
- Zeile 1: Typ-Indikator (
intoderstring) - Folgende Zeilen: Befehle bis
done
Zum Beispiel, bei folgender Eingabe:
int
enqueue 10
enqueue 20
enqueue 30
peek
dequeue
size
dequeue
dequeue
dequeue
doneSollte Ihre Ausgabe wie folgt aussehen:
10
10
2
20
30
emptyUnd bei folgender Eingabe:
string
enqueue hello
enqueue world
size
peek
dequeue
peek
doneSollte Ihre Ausgabe wie folgt aussehen:
2
hello
hello
worldIhre Queue sollte für Integer- und String-Typen identisch funktionieren und demonstrieren, wie eine einzige generische Implementierung mehrere konkrete Typen verarbeitet und dabei die volle Typsicherheit gewährleistet.
Probier es selbst
package main
import (
"bufio"
"fmt"
"os"
"strconv"
"strings"
)
func main() {
scanner := bufio.NewScanner(os.Stdin)
// Lies den Typ-Indikator
scanner.Scan()
typeIndicator := scanner.Text()
if typeIndicator == "int" {
// TODO: Erstelle eine Integer-Queue mit NewQueue[int]()
// Verarbeite Befehle für die Integer-Queue
for scanner.Scan() {
line := scanner.Text()
if line == "done" {
break
}
parts := strings.SplitN(line, " ", 2)
command := parts[0]
// TODO: Verarbeite Befehle: enqueue, dequeue, peek, size
// Für enqueue den Integer-Wert aus parts[1] parsen
// Für dequeue/peek "empty" ausgeben, wenn die Queue leer ist
_ = command
}
} else if typeIndicator == "string" {
// TODO: Erstelle eine String-Queue mit NewQueue[string]()
// Verarbeite Befehle für die String-Queue
for scanner.Scan() {
line := scanner.Text()
if line == "done" {
break
}
parts := strings.SplitN(line, " ", 2)
command := parts[0]
// TODO: Verarbeite Befehle: enqueue, dequeue, peek, size
// Für enqueue den String-Wert aus parts[1] verwenden
// Für dequeue/peek "empty" ausgeben, wenn die Queue leer ist
_ = command
}
}
// Diese sind hier, um Fehler wegen nicht verwendeter Imports während der Entwicklung zu vermeiden
_ = strconv.Atoi
_ = fmt.Println
}
Alle Lektionen in Objektorientierte Programmierung
1Grundlagen der Go OOP
Externe DateienGo Workspace & ModulePackages & ImportsExportierte vs. nicht-exportierte NamenEinführung in OOP in GoStructs als KlassenMethoden für Structs definierenPointer- vs. Value-ReceiverStruct-InitialisierungKonstruktor-FunktionenZusammenfassung – Einfacher Taschenrechner4Interfaces
Einführung in InterfacesImplizite ImplementierungInterface als VertragLeeres Interface (any)Type AssertionType SwitchInterface-KompositionStringer & Error InterfacesRückblick - Formen-Rechner7Kapselung
Exportierte vs. nicht exportierte FelderKapselung auf Paket-EbeneGetter- & Setter-MethodenInformation Hiding in GoZusammenfassung - Studierendendatensätze10Generics (Go 1.18+)
Einführung in GenericsTypparameterType ConstraintsGenerische StructsWorkaround für generische MethodenZusammenfassung – Generische Collection2Vertiefung: Typen & Structs
Basis- & zusammengesetzte TypenBenutzerdefinierte TypdefinitionenStruct TagsAnonyme StructsVerschachtelte StructsZero Values & StandardwerteZusammenfassung - Kontaktbuch5Komposition statt Vererbung
Warum Go keine Vererbung hatGrundlagen des Struct EmbeddingMethod PromotionEinbetten mehrerer StructsEmbedding vs. AggregationShadowing eingebetteter MethodenZusammenfassung – Mitarbeiter-Hierarchie8Fehlerbehandlung & OOP
Das error-InterfaceEigene FehlertypenError Wrapping (fmt.Errorf)Sentinel-Fehlererrors.Is() und errors.As()Panic, Defer und RecoverZusammenfassung – Datei-Parser3Zeiger & Speicher
Zeiger-Grundlagen in GoZeiger auf StructsWertübergabe vs. ReferenzübergabeDie new() FunktionGarbage Collection in GoWiederholung – Linked List Builder6Polymorphismus in Go
Polymorphismus über InterfacesDuck Typing in GoInterface-ErfüllungsregelnPolymorphe CollectionsDependency InjectionZusammenfassung – Payment Processor9Nebenläufigkeit & OOP
Goroutines GrundlagenChannels & KommunikationGepufferte vs. ungepufferte ChannelsSelect-Anweisungsync.Mutex & sync.RWMutexsync.WaitGroupThread-sicheres Struct-DesignZusammenfassung - Worker Pool