Punteros como valores de Map
Parte de la sección Lógica y Flujo del Journey de GO de Coddy. Lección 27 de 68.
Aunque almacenar estructuras directamente en mapas es útil, almacenar punteros a estructuras desbloquea una capacidad muy potente: la posibilidad de modificar directamente los datos de la estructura original a través del mapa. Este enfoque es esencial cuando necesitas actualizar tus datos después de haberlos almacenado.
Cuando almacenas un puntero a una estructura como valor de un mapa, almacenas la dirección de memoria de la estructura, no una copia de ella. Así es como declaras y trabajas con un mapa de este 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},
}La ventaja clave queda clara cuando necesitas modificar los datos. Como estás trabajando con punteros, los cambios realizados a través del mapa afectan a la estructura original:
// Actualiza el precio de la laptop directamente a través del mapa
products["laptop"].Price = 899.99
fmt.Println(products["laptop"].Price) // imprime: 899.99Este patrón es especialmente valioso en aplicaciones en las que necesitas actualizar con frecuencia los datos almacenados, como sistemas de inventario, perfiles de usuario o cualquier escenario en el que el mapa sirva como tu almacén de datos principal y las modificaciones deban persistir.
Desafío
FácilConstruye un sistema sencillo de gestión de inventario que demuestre el poder de usar punteros a estructuras como valores de un mapa. Este desafío muestra cómo los mapas basados en punteros permiten modificar directamente los datos almacenados, haciendo que tu sistema de inventario sea eficiente y responda a las actualizaciones.
Recibirás tres entradas:
- Una cadena que representa el número de productos (por ejemplo,
"4") - Una cadena que contiene los datos de los productos con el formato:
"name1:price1:quantity1,name2:price2:quantity2,name3:price3:quantity3"(por ejemplo,"laptop:999.99:5,mouse:25.50:20,keyboard:75.00:15,monitor:299.99:8") - Una cadena que contiene operaciones de actualización con el formato:
"operation1:product1:value1,operation2:product2:value2", donde las operaciones son"price"o"quantity"(por ejemplo,"price:laptop:899.99,quantity:mouse:25,price:keyboard:65.00")
Tu tarea es:
- Define una estructura
Productcon los siguientes campos:Price(float64): el precio del productoQuantity(int): la cantidad de productos en stock
- Crea un mapa donde las claves sean los nombres de los productos (cadenas) y los valores sean punteros a estructuras
Product - Analiza los datos de los productos de la segunda entrada:
- Divide la entrada por comas para obtener las entradas individuales de los productos
- Para cada entrada, divídela por dos puntos para separar el nombre, el precio y la cantidad
- Convierte la cadena del precio a un float64 y la cadena de la cantidad a un entero
- Crea una estructura
Producty almacena un puntero a ella en el mapa
- Mantén los nombres de los productos en un slice separado mientras los analizas, en el orden en que aparecen en la entrada. Recorrer un mapa en Go visita las claves en un orden aleatorio, por lo que el slice es lo que mantiene cada listado en el orden de entrada.
- Muestra el inventario inicial con el encabezado
"Initial Inventory:" - Muestra cada producto con el formato:
"[name]: $[price] (Stock: [quantity])" - Analiza y aplica las operaciones de actualización de la tercera entrada:
- Divide la entrada por comas para obtener las operaciones individuales
- Para cada operación, divídela por dos puntos para obtener el tipo de operación, el nombre del producto y el nuevo valor
- Actualiza el campo correspondiente directamente a través del puntero del mapa
- Imprime cada actualización con el formato:
"Updated [product]: [field] changed to [new_value]"
- Muestra el inventario actualizado con el encabezado
"Updated Inventory:" - Muestra cada producto nuevamente con el mismo formato que en la visualización inicial
- Calcula y muestra el valor total del inventario:
"Total Inventory Value: $[total_value]"
Usa el paquete strconv para convertir las cadenas de precios y cantidades a sus respectivos tipos numéricos. Da formato a todos los precios con 2 decimales al mostrarlos. Este desafío demuestra cómo almacenar punteros en mapas permite modificar directamente los datos de la estructura original, haciendo que las actualizaciones del inventario sean inmediatas y persistentes sin necesidad de reasignar valores al mapa.
Pruébalo tú mismo
package main
import (
"fmt"
"strconv"
"strings"
)
func main() {
// Leer entrada
var numProductsStr string
var productDataStr string
var operationsStr string
fmt.Scanln(&numProductsStr)
fmt.Scanln(&productDataStr)
fmt.Scanln(&operationsStr)
// TODO: Define la struct Product aquí
// TODO: Crea un map para almacenar punteros a productos
// TODO: Crea un slice para mantener el orden de los productos (para asegurar una salida consistente)
// TODO: Analiza los datos de productos y rellena el map
// Recuerda:
// - Divide productDataStr por comas para obtener entradas individuales
// - Para cada entrada, divide por dos puntos para obtener name, price, quantity
// - Convierte las cadenas de price y quantity a los tipos apropiados
// - Almacena el puntero a la struct Product en el map
// - Añade el name del producto al slice order
// TODO: Display initial inventory
// Usa el slice order para iterar a través de los productos de forma consistente
// Formato: "[name]: $[price] (Stock: [quantity])"
// TODO: Analizar y aplicar las operaciones de actualización
// Recuerda:
// - Dividir operationsStr por comas para obtener las operaciones individuales
// - Para cada operación, dividir por dos puntos para obtener type, name, value
// - Actualizar el campo apropiado directamente a través del puntero del map
// - Imprimir el mensaje de actualización para cada operación
// TODO: Display updated inventory
// De nuevo, usar el slice order para una salida consistente
// Calcular el valor total mientras se muestra
// TODO: Calculate and display total inventory value
// Format: "Total Inventory Value: $[total_value]"
}Esta lección incluye un breve cuestionario. Empieza la lección para responderlo y registrar tu progreso.
Todas las lecciones de Lógica y Flujo
1Flujo de control avanzado
Switch con `fallthrough`Salir de bucles anidadosContinuar un bucle específicoLa sentencia `goto`Repaso: Control de bucles avanzado4Proyecto: Lista de tareas sencilla
Configuración del proyectoAñadir una tarea2Estructuras y Métodos
Definición de métodos en estructurasReceptores de valorReceptores de punteroElegir receptoresMétodos vs FuncionesResumen - Comportamiento de estructuras5Mapas en profundidad
Mapas de StructsPunteros como valores de MapVerificación de Maps NilComparación de MapsResumen - Contador de frecuencia de palabras3Interfaces (Conceptos básicos)
¿Qué es una interfaz?Definir una interfazImplementar una interfazUso de tipos de interfazInterfaz vacíaAserciones de tipoType SwitchResumen: Formas y comportamientosPractica por tu cuenta: Compilador de Go online