Wskaźniki jako wartości map
Część sekcji Logika i przepływ sterowania ścieżki GO w Coddy. Lekcja 27 z 68.
Chociaż bezpośrednie przechowywanie struktur w mapach jest przydatne, przechowywanie wskaźników do struktur daje potężną możliwość: modyfikowania oryginalnych danych struktury bezpośrednio za pośrednictwem mapy. To podejście jest niezbędne, gdy musisz zaktualizować dane po ich zapisaniu.
Gdy przechowujesz wskaźnik do struktury jako wartość w mapie, przechowujesz adres pamięci struktury, a nie jej kopię. Oto jak deklarować mapę tego typu i z nią pracować:
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},
}Kluczowa zaleta staje się jasna, gdy trzeba zmodyfikować dane. Ponieważ pracujesz ze wskaźnikami, zmiany wprowadzone za pośrednictwem mapy wpływają na oryginalną strukturę:
// Zaktualizuj cenę laptopa bezpośrednio przez mapę
products["laptop"].Price = 899.99
fmt.Println(products["laptop"].Price) // wypisuje: 899.99Ten wzorzec jest szczególnie przydatny w aplikacjach, w których trzeba często aktualizować przechowywane dane, takich jak systemy zarządzania zapasami, profile użytkowników lub dowolne scenariusze, w których mapa służy jako główny magazyn danych, a wprowadzane modyfikacje muszą być trwałe.
Wyzwanie
ŁatwyZbuduj prosty system zarządzania zapasami, który pokazuje, jak wykorzystać wskaźniki do struktur jako wartości w mapie. To wyzwanie pokazuje, jak mapy oparte na wskaźnikach umożliwiają bezpośrednią modyfikację przechowywanych danych, dzięki czemu system zarządzania zapasami działa wydajnie i szybko reaguje na aktualizacje.
Otrzymasz trzy dane wejściowe:
- Ciąg znaków reprezentujący liczbę produktów (np.
"4") - Ciąg znaków zawierający dane produktów w formacie:
"name1:price1:quantity1,name2:price2:quantity2,name3:price3:quantity3"(np."laptop:999.99:5,mouse:25.50:20,keyboard:75.00:15,monitor:299.99:8") - Ciąg znaków zawierający operacje aktualizacji w formacie:
"operation1:product1:value1,operation2:product2:value2", gdzie operacje to"price"lub"quantity"(np."price:laptop:899.99,quantity:mouse:25,price:keyboard:65.00")
Twoje zadanie:
- Zdefiniuj strukturę
Productz następującymi polami:Price(float64) - cena produktuQuantity(int) - ilość produktu w magazynie
- Utwórz mapę, w której kluczami są nazwy produktów (ciągi znaków), a wartościami wskaźniki do struktur
Product - Przetwórz dane produktów z drugiego wejścia:
- Podziel dane wejściowe po przecinkach, aby uzyskać poszczególne wpisy produktów
- Dla każdego wpisu podziel go po dwukropkach, aby rozdzielić nazwę, cenę i ilość
- Przekonwertuj ciąg znaków z ceną na float64, a ciąg znaków z ilością na liczbę całkowitą
- Utwórz strukturę
Producti zapisz w mapie wskaźnik do niej
- Podczas przetwarzania przechowuj nazwy produktów w osobnej tablicy, w kolejności, w jakiej występują w danych wejściowych. Iterowanie po mapie w Go odwiedza klucze w losowej kolejności, dlatego tablica pozwala zachować kolejność z danych wejściowych na każdej liście.
- Wyświetl początkowy stan magazynu z nagłówkiem
"Initial Inventory:" - Wyświetl każdy produkt w formacie:
"[name]: $[price] (Stock: [quantity])" - Przetwórz i zastosuj operacje aktualizacji z trzeciego wejścia:
- Podziel dane wejściowe po przecinkach, aby uzyskać poszczególne operacje
- Dla każdej operacji podziel ją po dwukropkach, aby uzyskać typ operacji, nazwę produktu i nową wartość
- Zaktualizuj odpowiednie pole bezpośrednio za pośrednictwem wskaźnika w mapie
- Wyświetl każdą aktualizację w formacie:
"Updated [product]: [field] changed to [new_value]"
- Wyświetl zaktualizowany stan magazynu z nagłówkiem
"Updated Inventory:" - Ponownie wyświetl każdy produkt w tym samym formacie co przy wyświetlaniu początkowym
- Oblicz i wyświetl łączną wartość zapasów:
"Total Inventory Value: $[total_value]"
Użyj pakietu strconv, aby przekonwertować ciągi znaków z ceną i ilością na odpowiednie typy liczbowe. Podczas wyświetlania formatuj wszystkie ceny do 2 miejsc po przecinku. To wyzwanie pokazuje, że przechowywanie wskaźników w mapach pozwala bezpośrednio modyfikować dane oryginalnej struktury, dzięki czemu aktualizacje zapasów są natychmiastowe i trwałe, bez konieczności ponownego przypisywania wartości do mapy.
Spróbuj swoich sił
package main
import (
"fmt"
"strconv"
"strings"
)
func main() {
// Wczytaj dane wejściowe
var numProductsStr string
var productDataStr string
var operationsStr string
fmt.Scanln(&numProductsStr)
fmt.Scanln(&productDataStr)
fmt.Scanln(&operationsStr)
// TODO: Zdefiniuj tutaj strukturę Product
// TODO: Utwórz mapę do przechowywania wskaźników do produktów
// TODO: Utwórz wycinek do zachowania kolejności produktów (aby zapewnić spójne dane wyjściowe)
// TODO: Przeanalizuj dane produktów i wypełnij mapę
// Pamiętaj, aby:
// - Podziel productDataStr według przecinków, aby uzyskać poszczególne wpisy
// - Dla każdego wpisu podziel go według dwukropków, aby uzyskać nazwę, cenę i ilość
// - Przekonwertuj ciągi znaków zawierające cenę i ilość na odpowiednie typy
// - Zapisz w mapie wskaźnik do struktury Product
// - Dodaj nazwę produktu do wycinka przechowującego kolejność
// TODO: Wyświetl początkowy stan magazynowy
// Użyj wycinka order, aby przechodzić przez produkty w stałej kolejności
// Format: "[name]: $[price] (Stock: [quantity])"
// TODO: Przeanalizuj i zastosuj operacje aktualizacji
// Pamiętaj, aby:
// - Podziel operationsStr według przecinków, aby uzyskać poszczególne operacje
// - Dla każdej operacji podziel ją według dwukropków, aby uzyskać typ, nazwę i wartość
// - Zaktualizuj odpowiednie pole bezpośrednio przez wskaźnik w mapie
// - Wyświetl komunikat o aktualizacji dla każdej operacji
// TODO: Wyświetl zaktualizowany stan magazynowy
// Ponownie użyj wycinka order, aby zachować stałą kolejność wyświetlania
// Oblicz łączną wartość podczas wyświetlania
// TODO: Oblicz i wyświetl łączną wartość zapasów
// Format: "Total Inventory Value: $[total_value]"
}Ta lekcja zawiera krótki quiz. Zacznij lekcję, żeby na niego odpowiedzieć i śledzić swoje postępy.
Wszystkie lekcje w sekcji Logika i przepływ sterowania
1Zaawansowane sterowanie przepływem
Instrukcja switch z `fallthrough`Przerywanie zagnieżdżonych pętliKontynuowanie określonej pętliInstrukcja `goto`Podsumowanie — zaawansowane sterowanie pętlami4Projekt: Prosta lista zadań
Konfiguracja projektuDodawanie zadania2Struktury i metody
Definiowanie metod dla strukturOdbiorniki przez wartośćOdbiorniki przez wskaźnikWybór odbiornikówMetody a funkcjePodsumowanie — działanie struktur5Mapy w szczegółach
Mapy strukturWskaźniki jako wartości mapSprawdzanie, czy mapy są nilPorównywanie mapPodsumowanie — licznik częstości słów3Interfejsy (podstawy)
Czym jest interfejs?Definiowanie interfejsuImplementowanie interfejsuUżywanie typów interfejsowychPusty interfejsAsercje typuPrzełącznik typówPodsumowanie – kształty i zachowaniaPoćwicz samodzielnie: Kompilator Go online