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.
Si bien almacenar structs directamente en mapas es útil, almacenar punteros a structs desbloquea una capacidad poderosa: la capacidad de modificar los datos del struct original directamente a través del mapa. Este enfoque es esencial cuando necesitas actualizar tus datos después de que hayan sido almacenados.
Cuando almacenas un puntero a una estructura como valor de un mapa, estás almacenando la dirección de memoria de la estructura, no una copia de la misma. Así es como se declara y se trabaja 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 se vuelve clara cuando necesitas modificar los datos. Dado que estás trabajando con punteros, los cambios realizados a través del mapa afectan a la estructura original:
// Actualiza el precio del portátil directamente a través del mapa
products["laptop"].Price = 899.99
fmt.Println(products["laptop"].Price) // imprime: 899.99Este patrón es particularmente valioso en aplicaciones donde necesitas actualizar frecuentemente los datos almacenados, como sistemas de inventario, perfiles de usuario, o cualquier escenario donde el mapa sirva como tu almacén de datos principal y las modificaciones necesiten persistir.
Esta lección incluye un breve cuestionario. Empieza la lección para responderlo y registrar tu progreso.
Esta lección incluye un breve cuestionario. Empieza la lección para responderlo y registrar tu progreso.
Esta lección incluye un breve cuestionario. Empieza la lección para responderlo y registrar tu progreso.
Desafío
FácilConstruye un sistema simple 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 la modificación directa de los datos almacenados, haciendo que tu sistema de inventario sea eficiente y responda rápidamente 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 en 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 en 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:
- Definir una estructura
Productcon los siguientes campos:Price(float64) - el precio del productoQuantity(int) - la cantidad en stock del producto
- Crear un mapa donde las llaves sean nombres de productos (strings) y los valores sean punteros a estructuras
Product - Analizar los datos de los productos de la segunda entrada:
- Dividir la entrada por comas para obtener las entradas de productos individuales
- Para cada entrada, dividir por dos puntos para separar el nombre, el precio y la cantidad
- Convertir la cadena de precio a un float64 y la cadena de cantidad a un entero
- Crear una estructura
Producty almacenar un puntero a ella en el mapa
- Mostrar el inventario inicial con el encabezado
"Initial Inventory:" - Mostrar cada producto en el formato:
"[name]: $[price] (Stock: [quantity])" - Analizar y aplicar las operaciones de actualización de la tercera entrada:
- Dividir la entrada por comas para obtener las operaciones individuales
- Para cada operación, dividir por dos puntos para obtener el tipo de operación, el nombre del producto y el nuevo valor
- Actualizar el campo correspondiente directamente a través del puntero del mapa
- Imprimir cada actualización en el formato:
"Updated [product]: [field] changed to [new_value]"
- Mostrar el inventario actualizado con el encabezado
"Updated Inventory:" - Mostrar cada producto nuevamente en el mismo formato que la visualización inicial
- Calcular y mostrar el valor total del inventario:
"Total Inventory Value: $[total_value]"
Usa el paquete strconv para convertir las cadenas de precio y cantidad a sus respectivos tipos numéricos. Formatea todos los precios a 2 decimales al mostrarlos. Este desafío demuestra cómo almacenar punteros en mapas te permite modificar los datos de la estructura original directamente, haciendo que las actualizaciones de tu inventario sean inmediatas y persistentes sin necesidad de reasignar valores al mapa.
Hoja de referencia
Los mapas pueden almacenar punteros a estructuras, lo que permite la modificación directa de los datos de la estructura original a través del mapa:
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},
}Al usar punteros como valores del mapa, las modificaciones a través del mapa afectan a la estructura original:
// Actualiza el precio del portátil directamente a través del mapa
products["laptop"].Price = 899.99
fmt.Println(products["laptop"].Price) // imprime: 899.99Este patrón es valioso para aplicaciones que requieren actualizaciones de datos frecuentes, como sistemas de inventario o perfiles de usuario, donde el mapa sirve como el almacén de datos principal.
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: Definir la estructura Product aquí
// TODO: Crear un mapa para almacenar punteros de productos
// TODO: Crear un slice para mantener el orden de los productos (para asegurar una salida consistente)
// TODO: Analizar los datos del producto y poblar el mapa
// Recuerda:
// - Dividir productDataStr por comas para obtener entradas individuales
// - Para cada entrada, dividir por dos puntos para obtener nombre, precio, cantidad
// - Convertir las cadenas de precio y cantidad a los tipos apropiados
// - Almacenar el puntero a la estructura Product en el mapa
// - Añadir el nombre del producto al slice de orden
// TODO: Mostrar el inventario inicial
// Usar el slice de orden para iterar a través de los productos de manera consistente
// Formato: "[name]: $[price] (Stock: [quantity])"
// TODO: Analizar y aplicar operaciones de actualización
// Recuerda:
// - Dividir operationsStr por comas para obtener operaciones individuales
// - Para cada operación, dividir por dos puntos para obtener tipo, nombre, valor
// - Actualizar el campo apropiado directamente a través del puntero del mapa
// - Imprimir un mensaje de actualización para cada operación
// TODO: Mostrar el inventario actualizado
// Nuevamente, usar el slice de orden para una salida consistente
// Calcular el valor total mientras se muestra
// TODO: Calcular y mostrar el valor total del inventario
// Formato: "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 comportamientos