sort.Interface
Teil des Abschnitts Objektorientierte Programmierung der GO-Journey von Coddy — Lektion 74 von 107.
Das sort-Paket bietet ein weiteres hervorragendes Beispiel für Interface-basiertes Design. Um eine benutzerdefinierte Sammlung zu sortieren, muss Ihr Typ das sort.Interface implementieren:
type Interface interface {
Len() int
Less(i, j int) bool
Swap(i, j int)
}Diese drei Methoden geben dem Sortieralgorithmus alles, was er benötigt: die Länge der Sammlung, eine Möglichkeit, Elemente zu vergleichen, und eine Möglichkeit, sie zu vertauschen. Hier erfahren Sie, wie Sie einen Slice aus benutzerdefinierten Structs sortierbar machen:
type Person struct {
Name string
Age int
}
type ByAge []Person
func (a ByAge) Len() int { return len(a) }
func (a ByAge) Less(i, j int) bool { return a[i].Age < a[j].Age }
func (a ByAge) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
func main() {
people := []Person{
{"Alice", 30},
{"Bob", 25},
{"Carol", 35},
}
sort.Sort(ByAge(people))
fmt.Println(people)
// [{Bob 25} {Alice 30} {Carol 35}]
}Die entscheidende Erkenntnis ist das Erstellen eines benannten Typs (ByAge) basierend auf Ihrem Slice. Dies ermöglicht es Ihnen, verschiedene Sortierverhalten für dieselben Daten zu definieren. Sie könnten ByName mit einer anderen Less-Implementierung erstellen, um stattdessen alphabetisch zu sortieren.
Sobald Ihr Typ sort.Interface erfüllt, funktioniert er automatisch mit sort.Sort(), sort.Reverse() und sort.IsSorted().
Aufgabe
EinfachLassen Sie uns ein sortierbares Produktinventarsystem bauen, das die Leistungsfähigkeit von Gos sort.Interface demonstriert! Sie werden einen Product-Typ erstellen und mehrere Sortierstrategien implementieren, die es ermöglichen, dieselbe Sammlung auf verschiedene Arten zu sortieren.
Sie werden Ihren Code auf zwei Dateien aufteilen:
product.go: Definieren Sie Ihren Produkttyp und die Sortierimplementierungen.Erstellen Sie ein
Product-Struct mit drei Feldern:Name(string),Price(float64) undQuantity(int).Erstellen Sie zwei benannte Typen basierend auf
[]Product:ByPrice- zum Sortieren von Produkten nach Preis in aufsteigender ReihenfolgeByQuantity- zum Sortieren von Produkten nach Menge in absteigender Reihenfolge (höchste Menge zuerst)
Jeder Typ muss die drei vom
sort.Interfacegeforderten Methoden implementieren:Len(),Less(i, j int)undSwap(i, j int). DieLess-Methode bestimmt die Sortierreihenfolge für jeden Typ.main.go: Erstellen und sortieren Sie Ihr Produktinventar.Lesen Sie einen Sortiermodus (
priceoderquantity) ein, lesen Sie dann eine Anzahl gefolgt von Produktdetails. Jedes Produkt wird in drei Zeilen angegeben: Name, Preis und Menge.Erstellen Sie ein Slice von Produkten, sortieren Sie diese mit dem entsprechenden Sortiertyp basierend auf dem Modus und geben Sie dann jedes Produkt in diesem Format aus:
[Name]: $[Price] (x[Quantity])Zeigen Sie Preise mit zwei Dezimalstellen an.
Die folgenden Eingaben werden bereitgestellt:
- Zeile 1: Sortiermodus (
priceoderquantity) - Zeile 2: Anzahl der Produkte
- Folgende Zeilen: Produktdetails (Name, Preis, Menge - drei Zeilen pro Produkt)
Zum Beispiel, gegeben:
price
3
Laptop
999.99
5
Mouse
29.99
50
Keyboard
79.99
25Ihre Ausgabe sollte sein:
Mouse: $29.99 (x50)
Keyboard: $79.99 (x25)
Laptop: $999.99 (x5)Und gegeben:
quantity
3
Laptop
999.99
5
Mouse
29.99
50
Keyboard
79.99
25Ihre Ausgabe sollte sein:
Mouse: $29.99 (x50)
Keyboard: $79.99 (x25)
Laptop: $999.99 (x5)Beachten Sie, wie dieselben Produktdaten unterschiedlich sortiert werden können, indem Sie einfach einen anderen benannten Typ verwenden. Sobald Ihre Typen das sort.Interface erfüllen, arbeiten sie nahtlos mit sort.Sort() aus der Standardbibliothek zusammen.
Spickzettel
Das Paket sort erfordert, dass Typen das sort.Interface implementieren, um sortierbar zu sein:
type Interface interface {
Len() int
Less(i, j int) bool
Swap(i, j int)
}Um ein benutzerdefiniertes Slice sortierbar zu machen, erstellen Sie einen benannten Typ und implementieren Sie die drei erforderlichen Methoden:
type Person struct {
Name string
Age int
}
type ByAge []Person
func (a ByAge) Len() int { return len(a) }
func (a ByAge) Less(i, j int) bool { return a[i].Age < a[j].Age }
func (a ByAge) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
// Die Sammlung sortieren
sort.Sort(ByAge(people))Sie können mehrere benannte Typen für dasselbe Slice erstellen, um verschiedene Sortierverhalten zu implementieren. Jeder Typ definiert seine eigene Less-Methode, um die Sortierreihenfolge festzulegen.
Sobald ein Typ das sort.Interface erfüllt, funktioniert er mit sort.Sort(), sort.Reverse() und sort.IsSorted().
Probier es selbst
package main
import (
"bufio"
"fmt"
"os"
"sort"
"strconv"
)
func main() {
reader := bufio.NewReader(os.Stdin)
// Sortiermodus lesen
var mode string
fmt.Fscanln(reader, &mode)
// Anzahl der Produkte lesen
var count int
fmt.Fscanln(reader, &count)
// Produkte lesen
products := make([]Product, count)
for i := 0; i < count; i++ {
name, _ := reader.ReadString('\n')
name = name[:len(name)-1] // Zeilenumbruch entfernen
priceStr, _ := reader.ReadString('\n')
priceStr = priceStr[:len(priceStr)-1]
price, _ := strconv.ParseFloat(priceStr, 64)
qtyStr, _ := reader.ReadString('\n')
qtyStr = qtyStr[:len(qtyStr)-1]
quantity, _ := strconv.Atoi(qtyStr)
products[i] = Product{Name: name, Price: price, Quantity: quantity}
}
// TODO: Produkte basierend auf dem Modus sortieren
// Wenn der Modus "price" ist, verwende den Typ ByPrice
// Wenn der Modus "quantity" ist, verwende den Typ ByQuantity
// Verwende sort.Sort() mit dem entsprechenden Typ
// TODO: Jedes Produkt im folgenden Format ausgeben:
// [Name]: $[Price] (x[Quantity])
// Verwende fmt.Printf mit %.2f für die Preisformatierung
}
Diese Lektion enthält ein kurzes Quiz. Starte die Lektion, um es zu beantworten und deinen Fortschritt zu speichern.
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-Parser11Standardbibliothek & OOP
io.Reader & io.Writersort.Interfacefmt.Stringer Interfaceencoding/json mit Structshttp.Handler InterfaceZusammenfassung - REST-API-Modelle3Zeiger & 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