Pointer als Map-Werte
Teil des Abschnitts Logik & Ablauf der GO-Journey von Coddy — Lektion 27 von 68.
Während das direkte Speichern von Structs in Maps nützlich ist, schaltet das Speichern von Pointern auf Structs eine leistungsstarke Funktion frei: die Fähigkeit, die ursprünglichen Struct-Daten direkt über die Map zu ändern. Dieser Ansatz ist unerlässlich, wenn Sie Ihre Daten aktualisieren müssen, nachdem sie gespeichert wurden.
Wenn Sie einen Zeiger auf ein Struct als Map-Wert speichern, speichern Sie die Speicheradresse des Structs, nicht eine Kopie davon. So deklarieren und arbeiten Sie mit einer solchen Map:
type Product struct {
Price float64
Quantity int
}
products := map[string]*Product{
"laptop": &Product{Price: 999.99, Quantity: 5},
"mouse": &Product{Price: 25.50, Quantity: 20},
}Der entscheidende Vorteil wird deutlich, wenn Sie die Daten ändern müssen. Da Sie mit Pointern arbeiten, wirken sich Änderungen, die über die Map vorgenommen werden, auf das ursprüngliche Struct aus:
// Aktualisieren Sie den Preis des Laptops direkt über die Map
products["laptop"].Price = 899.99
fmt.Println(products["laptop"].Price) // gibt aus: 899.99Dieses Muster ist besonders wertvoll in Anwendungen, in denen Sie gespeicherte Daten häufig aktualisieren müssen, wie z. B. Inventarsysteme, Benutzerprofile oder jedes Szenario, in dem die Map als Ihr primärer Datenspeicher dient und Änderungen dauerhaft gespeichert werden müssen.
Diese Lektion enthält ein kurzes Quiz. Starte die Lektion, um es zu beantworten und deinen Fortschritt zu speichern.
Diese Lektion enthält ein kurzes Quiz. Starte die Lektion, um es zu beantworten und deinen Fortschritt zu speichern.
Diese Lektion enthält ein kurzes Quiz. Starte die Lektion, um es zu beantworten und deinen Fortschritt zu speichern.
Aufgabe
EinfachErstellen Sie ein einfaches Bestandsverwaltungssystem, das die Vorteile der Verwendung von Pointern auf Structs als Map-Werte demonstriert. Diese Herausforderung zeigt, wie Pointer-basierte Maps die direkte Änderung gespeicherter Daten ermöglichen, wodurch Ihr Inventarsystem effizient wird und schnell auf Aktualisierungen reagiert.
Sie erhalten drei Eingaben:
- Einen String, der die Anzahl der Produkte darstellt (z. B.
"4") - Einen String, der Produktdaten im Format enthält:
"name1:price1:quantity1,name2:price2:quantity2,name3:price3:quantity3"(z. B."laptop:999.99:5,mouse:25.50:20,keyboard:75.00:15,monitor:299.99:8") - Einen String, der Aktualisierungsoperationen im Format enthält:
"operation1:product1:value1,operation2:product2:value2"wobei Operationen entweder"price"oder"quantity"sind (z. B."price:laptop:899.99,quantity:mouse:25,price:keyboard:65.00")
Ihre Aufgabe ist es:
- Definieren Sie ein
ProductStruct mit den folgenden Feldern:Price(float64) - der Preis des ProduktsQuantity(int) - die Lagerbestandsmenge des Produkts
- Erstellen Sie eine Map, in der die Schlüssel Produktnamen (Strings) und die Werte Pointer auf
ProductStructs sind - Verarbeiten Sie die Produktdaten aus der zweiten Eingabe:
- Teilen Sie die Eingabe durch Kommas auf, um einzelne Produkteinträge zu erhalten
- Teilen Sie jeden Eintrag durch Doppelpunkte auf, um Name, Preis und Menge zu trennen
- Konvertieren Sie den Preis-String in einen float64 und den Mengen-String in einen Integer
- Erstellen Sie ein
ProductStruct und speichern Sie einen Pointer darauf in der Map
- Zeigen Sie das ursprüngliche Inventar mit der Kopfzeile
"Initial Inventory:"an - Geben Sie jedes Produkt im Format:
"[name]: $[price] (Stock: [quantity])"aus - Verarbeiten und wenden Sie die Aktualisierungsoperationen aus der dritten Eingabe an:
- Teilen Sie die Eingabe durch Kommas auf, um einzelne Operationen zu erhalten
- Teilen Sie jede Operation durch Doppelpunkte auf, um Operationstyp, Produktname und neuen Wert zu erhalten
- Aktualisieren Sie das entsprechende Feld direkt über den Map-Pointer
- Geben Sie jede Aktualisierung im Format:
"Updated [product]: [field] changed to [new_value]"aus
- Zeigen Sie das aktualisierte Inventar mit der Kopfzeile
"Updated Inventory:"an - Geben Sie jedes Produkt erneut im gleichen Format wie bei der ursprünglichen Anzeige aus
- Berechnen und zeigen Sie den Gesamtwert des Inventars an:
"Total Inventory Value: $[total_value]"
Verwenden Sie das strconv Paket, um Preis- und Mengen-Strings in ihre jeweiligen numerischen Typen zu konvertieren. Formatieren Sie alle Preise bei der Anzeige auf 2 Dezimalstellen. Diese Herausforderung zeigt, wie das Speichern von Pointern in Maps es Ihnen ermöglicht, die ursprünglichen Struct-Daten direkt zu ändern, wodurch Ihre Inventaraktualisierungen sofort und dauerhaft erfolgen, ohne dass Werte der Map neu zugewiesen werden müssen.
Spickzettel
Maps können Pointer auf Structs speichern, was die direkte Änderung der ursprünglichen Struct-Daten über die Map ermöglicht:
type Product struct {
Price float64
Quantity int
}
products := map[string]*Product{
"laptop": &Product{Price: 999.99, Quantity: 5},
"mouse": &Product{Price: 25.50, Quantity: 20},
}Wenn Pointer als Map-Werte verwendet werden, wirken sich Änderungen über die Map auf das ursprüngliche Struct aus:
// Den Preis des Laptops direkt über die Map aktualisieren
products["laptop"].Price = 899.99
fmt.Println(products["laptop"].Price) // gibt aus: 899.99Dieses Muster ist wertvoll für Anwendungen, die häufige Datenaktualisierungen erfordern, wie z. B. Inventarsysteme oder Benutzerprofile, bei denen die Map als primärer Datenspeicher dient.
Probier es selbst
package main
import (
"fmt"
"strconv"
"strings"
)
func main() {
// Eingabe lesen
var numProductsStr string
var productDataStr string
var operationsStr string
fmt.Scanln(&numProductsStr)
fmt.Scanln(&productDataStr)
fmt.Scanln(&operationsStr)
// TODO: Product-Struktur hier definieren
// TODO: Map erstellen, um Produkt-Pointer zu speichern
// TODO: Slice erstellen, um die Produktreihenfolge beizubehalten (für konsistente Ausgabe)
// TODO: Produktdaten parsen und die Map befüllen
// Nicht vergessen:
// - productDataStr nach Kommas trennen, um einzelne Einträge zu erhalten
// - Jeden Eintrag nach Doppelpunkten trennen, um Name, Preis und Menge zu erhalten
// - Preis- und Mengen-Strings in entsprechende Typen umwandeln
// - Pointer zur Product-Struktur in der Map speichern
// - Produktnamen zum Order-Slice hinzufügen
// TODO: Anfangsbestand anzeigen
// Den Order-Slice verwenden, um Produkte konsistent zu durchlaufen
// Format: "[name]: $[price] (Stock: [quantity])"
// TODO: Aktualisierungsoperationen parsen und anwenden
// Nicht vergessen:
// - operationsStr nach Kommas trennen, um einzelne Operationen zu erhalten
// - Jede Operation nach Doppelpunkten trennen, um Typ, Name und Wert zu erhalten
// - Das entsprechende Feld direkt über den Map-Pointer aktualisieren
// - Aktualisierungsnachricht für jede Operation ausgeben
// TODO: Aktualisierten Bestand anzeigen
// Wieder den Order-Slice für eine konsistente Ausgabe verwenden
// Gesamtwert während der Anzeige berechnen
// TODO: Gesamtwert des Bestands berechnen und anzeigen
// Format: "Total Inventory Value: $[total_value]"
}Diese Lektion enthält ein kurzes Quiz. Starte die Lektion, um es zu beantworten und deinen Fortschritt zu speichern.
Alle Lektionen in Logik & Ablauf
1Fortgeschrittener Kontrollfluss
Switch mit `fallthrough`Abbrechen von verschachtelten SchleifenFortsetzen einer bestimmten SchleifeDie `goto`-AnweisungZusammenfassung – Fortgeschrittene Schleifensteuerung4Projekt: Einfache Aufgabenliste
Projekt-SetupEine Aufgabe hinzufügen2Structs und Methoden
Methoden für Structs definierenValue ReceiverPointer ReceiverReceiver auswählenMethoden vs. FunktionenZusammenfassung – Struct-Verhalten5Maps im Detail
Maps von StructsPointer als Map-WertePrüfen auf Nil-MapsMaps vergleichenZusammenfassung – Wortfrequenz-Zähler8Projekt: Einfache Bestandsverwaltung
ProjektübersichtLagerbestand prüfen11Abschlussherausforderungen
Einfache KontaktlisteEinfacher Zahlen-ValidatorSammler für eindeutige Elemente3Interfaces (Die Grundlagen)
Was ist ein Interface?Ein Interface definierenEin Interface implementierenInterface-Typen verwendenLeeres InterfaceType AssertionsType SwitchZusammenfassung – Formen und Verhalten