Puntatori come valori delle mappe
Fa parte della sezione Logica e flusso del percorso GO di Coddy. Lezione 27 di 68.
Anche se memorizzare le struct direttamente nelle mappe è utile, memorizzare puntatori alle struct sblocca una potente possibilità: modificare direttamente i dati della struct originale tramite la mappa. Questo approccio è essenziale quando devi aggiornare i dati dopo averli memorizzati.
Quando memorizzi un puntatore a una struct come valore di una mappa, stai memorizzando l'indirizzo di memoria della struct, non una sua copia. Ecco come dichiarare e usare una mappa di questo tipo:
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},
}Il vantaggio principale diventa chiaro quando devi modificare i dati. Poiché stai lavorando con puntatori, le modifiche apportate tramite la mappa influiscono sulla struct originale:
// Actualiza el precio del portátil directamente a través del mapa
products["laptop"].Price = 899.99
fmt.Println(products["laptop"].Price) // imprime: 899.99Questo schema è particolarmente utile nelle applicazioni in cui devi aggiornare frequentemente i dati memorizzati, come nei sistemi di inventario, nei profili utente o in qualsiasi scenario in cui la mappa funge da archivio dati principale e le modifiche devono essere mantenute.
Sfida
FacileCrea un semplice sistema di gestione dell'inventario che dimostri i vantaggi dell'uso di puntatori a struct come valori di una mappa. Questa sfida mostra come le mappe basate su puntatori consentano di modificare direttamente i dati memorizzati, rendendo il sistema di inventario efficiente e reattivo agli aggiornamenti.
Riceverai tre input:
- Una stringa che rappresenta il numero di prodotti (ad es.,
"4") - Una stringa contenente i dati dei prodotti nel formato:
"name1:price1:quantity1,name2:price2:quantity2,name3:price3:quantity3"(ad es.,"laptop:999.99:5,mouse:25.50:20,keyboard:75.00:15,monitor:299.99:8") - Una stringa contenente le operazioni di aggiornamento nel formato:
"operation1:product1:value1,operation2:product2:value2", dove le operazioni sono"price"oppure"quantity"(ad es.,"price:laptop:899.99,quantity:mouse:25,price:keyboard:65.00")
Il tuo compito è:
- Definire una struct
Productcon i seguenti campi:Price(float64) - il prezzo del prodottoQuantity(int) - la quantità del prodotto in magazzino
- Creare una mappa in cui le chiavi sono i nomi dei prodotti (stringhe) e i valori sono puntatori a struct
Product - Analizzare i dati dei prodotti dal secondo input:
- Dividere l'input usando le virgole per ottenere le singole voci dei prodotti
- Per ogni voce, dividerla usando i due punti per separare il nome, il prezzo e la quantità
- Convertire la stringa del prezzo in un float64 e la stringa della quantità in un intero
- Creare una struct
Producte memorizzarne un puntatore nella mappa
- Durante l'analisi, mantenere i nomi dei prodotti in uno slice separato, nell'ordine in cui compaiono nell'input. In Go, l'iterazione su una mappa visita le chiavi in ordine casuale, quindi è lo slice a mantenere ogni elenco nell'ordine dell'input.
- Visualizzare l'inventario iniziale con l'intestazione
"Initial Inventory:" - Mostrare ogni prodotto nel formato:
"[name]: $[price] (Stock: [quantity])" - Analizzare e applicare le operazioni di aggiornamento dal terzo input:
- Dividere l'input usando le virgole per ottenere le singole operazioni
- Per ogni operazione, dividerla usando i due punti per ottenere il tipo di operazione, il nome del prodotto e il nuovo valore
- Aggiornare direttamente il campo appropriato tramite il puntatore nella mappa
- Stampare ogni aggiornamento nel formato:
"Updated [product]: [field] changed to [new_value]"
- Visualizzare l'inventario aggiornato con l'intestazione
"Updated Inventory:" - Mostrare di nuovo ogni prodotto usando lo stesso formato della visualizzazione iniziale
- Calcolare e visualizzare il valore totale dell'inventario:
"Total Inventory Value: $[total_value]"
Usa il package strconv per convertire le stringhe di prezzo e quantità nei rispettivi tipi numerici. Quando visualizzi i prezzi, formattali tutti con 2 cifre decimali. Questa sfida dimostra come memorizzare puntatori nelle mappe permetta di modificare direttamente i dati della struct originale, rendendo gli aggiornamenti dell'inventario immediati e persistenti senza dover riassegnare i valori alla mappa.
Provalo tu
package main
import (
"fmt"
"strconv"
"strings"
)
func main() {
// Leggi l'input
var numProductsStr string
var productDataStr string
var operationsStr string
fmt.Scanln(&numProductsStr)
fmt.Scanln(&productDataStr)
fmt.Scanln(&operationsStr)
// TODO: Definisci qui la struct Product
// TODO: Crea una mappa per memorizzare i puntatori ai prodotti
// TODO: Crea una slice per mantenere l'ordine dei prodotti (per garantire un output coerente)
// TODO: Analizza i dati dei prodotti e popola la mappa
// Ricorda di:
// - Suddividere productDataStr in corrispondenza delle virgole per ottenere le singole voci
// - Per ogni voce, suddividerla in corrispondenza dei due punti per ottenere nome, prezzo e quantità
// - Convertire le stringhe del prezzo e della quantità nei tipi appropriati
// - Memorizzare nella mappa un puntatore alla struct Product
// - Aggiungere il nome del prodotto alla slice dell'ordine
// TODO: Mostra l'inventario iniziale
// Usa la slice order per scorrere i prodotti in modo coerente
// Formato: "[name]: $[price] (Stock: [quantity])"
// TODO: Analizza e applica le operazioni di aggiornamento
// Ricorda di:
// - Dividi operationsStr in corrispondenza delle virgole per ottenere le singole operazioni
// - Per ogni operazione, dividi in corrispondenza dei due punti per ottenere tipo, nome e valore
// - Aggiorna il campo appropriato direttamente tramite il puntatore nella map
// - Stampa un messaggio di aggiornamento per ogni operazione
// TODO: Mostra l'inventario aggiornato
// Usa di nuovo la slice order per ottenere un output coerente
// Calcola il valore totale mentre visualizzi l'inventario
// TODO: Calcola e mostra il valore totale dell'inventario
// Formato: "Total Inventory Value: $[total_value]"
}Questa lezione include un breve quiz. Inizia la lezione per rispondere e tenere traccia dei tuoi progressi.
Tutte le lezioni di Logica e flusso
1Flusso di controllo avanzato
Switch con `fallthrough`Uscire dai cicli annidatiContinuare un ciclo specificoL'istruzione `goto`Riepilogo - Controllo avanzato dei cicli4Progetto: semplice lista di attività
Configurazione del progettoAggiungere un’attività2Struct e metodi
Definire metodi sugli structReceiver per valoreReceiver con puntatoreScegliere i receiverMetodi vs funzioniRiepilogo - comportamento degli struct5Mappe in dettaglio
Mappe di structPuntatori come valori delle mappeVerificare le mappe nilConfrontare le mappeRiepilogo - Contatore della frequenza delle parole3Interfacce (le basi)
Che cos’è un’interfaccia?Definire un’interfacciaImplementare un’interfacciaUsare i tipi interfacciaInterfaccia vuotaAsserzioni di tipoSwitch di tipoRiepilogo: forme e comportamentiEsercitati da solo: Compilatore Go online