Pointers as Map Values
Part of the Logic & Flow section of Coddy's GO journey — lesson 27 of 68.
While storing structs directly in maps is useful, storing pointers to structs unlocks a powerful capability: the ability to modify the original struct data directly through the map. This approach is essential when you need to update your data after it's been stored.
When you store a pointer to a struct as a map value, you're storing the memory address of the struct, not a copy of it. Here's how you declare and work with such a 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},
}The key advantage becomes clear when you need to modify the data. Since you're working with pointers, changes made through the map affect the original struct:
// Update the laptop's price directly through the map
products["laptop"].Price = 899.99
fmt.Println(products["laptop"].Price) // prints: 899.99This pattern is particularly valuable in applications where you need to frequently update stored data, such as inventory systems, user profiles, or any scenario where the map serves as your primary data store and modifications need to persist.
This lesson includes a short quiz. Start the lesson to answer it and track your progress.
This lesson includes a short quiz. Start the lesson to answer it and track your progress.
This lesson includes a short quiz. Start the lesson to answer it and track your progress.
Challenge
EasyBuild a simple inventory management system that demonstrates the power of using pointers to structs as map values. This challenge shows how pointer-based maps enable direct modification of stored data, making your inventory system efficient and responsive to updates.
You will receive three inputs:
- A string representing the number of products (e.g.,
"4") - A string containing product data in the format:
"name1:price1:quantity1,name2:price2:quantity2,name3:price3:quantity3"(e.g.,"laptop:999.99:5,mouse:25.50:20,keyboard:75.00:15,monitor:299.99:8") - A string containing update operations in the format:
"operation1:product1:value1,operation2:product2:value2"where operations are either"price"or"quantity"(e.g.,"price:laptop:899.99,quantity:mouse:25,price:keyboard:65.00")
Your task is to:
- Define a
Productstruct with the following fields:Price(float64) - the product's priceQuantity(int) - the product's stock quantity
- Create a map where the keys are product names (strings) and the values are pointers to
Productstructs - Parse the product data from the second input:
- Split the input by commas to get individual product entries
- For each entry, split by colons to separate name, price, and quantity
- Convert the price string to a float64 and quantity string to an integer
- Create a
Productstruct and store a pointer to it in the map
- Display the initial inventory with the header
"Initial Inventory:" - Show each product in the format:
"[name]: $[price] (Stock: [quantity])" - Parse and apply the update operations from the third input:
- Split the input by commas to get individual operations
- For each operation, split by colons to get operation type, product name, and new value
- Update the appropriate field directly through the map pointer
- Print each update in the format:
"Updated [product]: [field] changed to [new_value]"
- Display the updated inventory with the header
"Updated Inventory:" - Show each product again in the same format as the initial display
- Calculate and display the total inventory value:
"Total Inventory Value: $[total_value]"
Use the strconv package to convert price and quantity strings to their respective numeric types. Format all prices to 2 decimal places when displaying. This challenge demonstrates how storing pointers in maps allows you to modify the original struct data directly, making your inventory updates immediate and persistent without needing to reassign values to the map.
Cheat sheet
Maps can store pointers to structs, allowing direct modification of the original struct data through the 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},
}When using pointers as map values, modifications through the map affect the original struct:
// Update the laptop's price directly through the map
products["laptop"].Price = 899.99
fmt.Println(products["laptop"].Price) // prints: 899.99This pattern is valuable for applications requiring frequent data updates, such as inventory systems or user profiles, where the map serves as the primary data store.
Try it yourself
package main
import (
"fmt"
"strconv"
"strings"
)
func main() {
// Read input
var numProductsStr string
var productDataStr string
var operationsStr string
fmt.Scanln(&numProductsStr)
fmt.Scanln(&productDataStr)
fmt.Scanln(&operationsStr)
// TODO: Define Product struct here
// TODO: Create map to store product pointers
// TODO: Create slice to maintain product order (to ensure consistent output)
// TODO: Parse product data and populate the map
// Remember to:
// - Split productDataStr by commas to get individual entries
// - For each entry, split by colons to get name, price, quantity
// - Convert price and quantity strings to appropriate types
// - Store pointer to Product struct in map
// - Add product name to order slice
// TODO: Display initial inventory
// Use the order slice to iterate through products consistently
// Format: "[name]: $[price] (Stock: [quantity])"
// TODO: Parse and apply update operations
// Remember to:
// - Split operationsStr by commas to get individual operations
// - For each operation, split by colons to get type, name, value
// - Update the appropriate field directly through the map pointer
// - Print update message for each operation
// TODO: Display updated inventory
// Again, use the order slice for consistent output
// Calculate total value while displaying
// TODO: Calculate and display total inventory value
// Format: "Total Inventory Value: $[total_value]"
}This lesson includes a short quiz. Start the lesson to answer it and track your progress.
All lessons in Logic & Flow
1Advanced Control Flow
Switch with `fallthrough`Breaking from Nested LoopsContinuing a Specific LoopThe `goto` StatementRecap - Advanced Loop Control4Project: Simple Task List
Project SetupAdding a Task2Structs and Methods
Defining Methods on StructsValue ReceiversPointer ReceiversChoosing ReceiversMethods vs FunctionsRecap - Struct Behavior5Maps In-Depth
Maps of StructsPointers as Map ValuesTesting for Nil MapsComparing MapsRecap - Word Frequency Counter3Interfaces (The Basics)
What is an Interface?Defining an InterfaceImplementing an InterfaceUsing Interface TypesEmpty InterfaceType AssertionsType SwitchRecap - Shapes and Behaviors