Ponteiros como Valores de Map
Parte da seção Lógica & Fluxo do Journey de GO da Coddy — lição 27 de 68.
Embora armazenar structs diretamente em maps seja útil, armazenar ponteiros para structs desbloqueia uma capacidade poderosa: a habilidade de modificar os dados da struct original diretamente através do map. Esta abordagem é essencial quando você precisa atualizar seus dados após eles terem sido armazenados.
Quando você armazena um ponteiro para uma struct como um valor de mapa, você está armazenando o endereço de memória da struct, não uma cópia dela. Veja como declarar e trabalhar com esse tipo de 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},
}A principal vantagem torna-se clara quando você precisa modificar os dados. Como você está trabalhando com ponteiros, as alterações feitas por meio do mapa afetam a struct original:
// Atualiza o preço do laptop diretamente através do mapa
products["laptop"].Price = 899.99
fmt.Println(products["laptop"].Price) // imprime: 899.99Este padrão é particularmente valioso em aplicações onde você precisa atualizar dados armazenados frequentemente, como sistemas de inventário, perfis de usuário ou qualquer cenário onde o mapa serve como seu armazenamento de dados primário e as modificações precisam persistir.
Esta lição inclui um quiz rápido. Comece a lição para respondê-lo e acompanhar seu progresso.
Esta lição inclui um quiz rápido. Comece a lição para respondê-lo e acompanhar seu progresso.
Esta lição inclui um quiz rápido. Comece a lição para respondê-lo e acompanhar seu progresso.
Desafio
FácilConstrua um sistema simples de gerenciamento de inventário que demonstre o poder de usar ponteiros para structs como valores de um mapa. Este desafio mostra como mapas baseados em ponteiros permitem a modificação direta dos dados armazenados, tornando seu sistema de inventário eficiente e responsivo a atualizações.
Você receberá três entradas:
- Uma string representando o número de produtos (ex:
"4") - Uma string contendo os dados dos produtos no formato:
"name1:price1:quantity1,name2:price2:quantity2,name3:price3:quantity3"(ex:"laptop:999.99:5,mouse:25.50:20,keyboard:75.00:15,monitor:299.99:8") - Uma string contendo operações de atualização no formato:
"operation1:product1:value1,operation2:product2:value2"onde as operações são"price"ou"quantity"(ex:"price:laptop:899.99,quantity:mouse:25,price:keyboard:65.00")
Sua tarefa é:
- Definir uma struct
Productcom os seguintes campos:Price(float64) - o preço do produtoQuantity(int) - a quantidade em estoque do produto
- Criar um mapa onde as chaves são nomes de produtos (strings) e os valores são ponteiros para structs
Product - Analisar os dados dos produtos da segunda entrada:
- Dividir a entrada por vírgulas para obter as entradas individuais de produtos
- Para cada entrada, dividir por dois-pontos para separar nome, preço e quantidade
- Converter a string de preço para um float64 e a string de quantidade para um inteiro
- Criar uma struct
Producte armazenar um ponteiro para ela no mapa
- Exibir o inventário inicial com o cabeçalho
"Initial Inventory:" - Mostrar cada produto no formato:
"[name]: $[price] (Stock: [quantity])" - Analisar e aplicar as operações de atualização da terceira entrada:
- Dividir a entrada por vírgulas para obter as operações individuais
- Para cada operação, dividir por dois-pontos para obter o tipo de operação, o nome do produto e o novo valor
- Atualizar o campo apropriado diretamente através do ponteiro no mapa
- Imprimir cada atualização no formato:
"Updated [product]: [field] changed to [new_value]"
- Exibir o inventário atualizado com o cabeçalho
"Updated Inventory:" - Mostrar cada produto novamente no mesmo formato da exibição inicial
- Calcular e exibir o valor total do inventário:
"Total Inventory Value: $[total_value]"
Use o pacote strconv para converter as strings de preço e quantidade em seus respectivos tipos numéricos. Formate todos os preços com 2 casas decimais ao exibir. Este desafio demonstra como armazenar ponteiros em mapas permite que você modifique os dados originais da struct diretamente, tornando as atualizações do seu inventário imediatas e persistentes sem a necessidade de reatribuir valores ao mapa.
Folha de consulta
Maps podem armazenar ponteiros para structs, permitindo a modificação direta dos dados da struct original através do 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},
}Ao usar ponteiros como valores de um map, as modificações feitas através do map afetam a struct original:
// Update the laptop's price directly through the map
products["laptop"].Price = 899.99
fmt.Println(products["laptop"].Price) // imprime: 899.99Este padrão é valioso para aplicações que exigem atualizações frequentes de dados, como sistemas de inventário ou perfis de usuário, onde o map serve como o armazenamento de dados primário.
Experimente você mesmo
package main
import (
"fmt"
"strconv"
"strings"
)
func main() {
// Ler a entrada
var numProductsStr string
var productDataStr string
var operationsStr string
fmt.Scanln(&numProductsStr)
fmt.Scanln(&productDataStr)
fmt.Scanln(&operationsStr)
// TODO: Definir a struct Product aqui
// TODO: Criar um map para armazenar ponteiros de produtos
// TODO: Criar um slice para manter a ordem dos produtos (para garantir uma saída consistente)
// TODO: Analisar os dados dos produtos e preencher o map
// Lembre-se de:
// - Dividir productDataStr por vírgulas para obter entradas individuais
// - Para cada entrada, dividir por dois pontos para obter nome, preço, quantidade
// - Converter as strings de preço e quantidade para os tipos apropriados
// - Armazenar o ponteiro para a struct Product no map
// - Adicionar o nome do produto ao slice de ordem
// TODO: Exibir o inventário inicial
// Use o slice de ordem para iterar pelos produtos de forma consistente
// Formato: "[name]: $[price] (Stock: [quantity])"
// TODO: Analisar e aplicar as operações de atualização
// Lembre-se de:
// - Dividir operationsStr por vírgulas para obter operações individuais
// - Para cada operação, dividir por dois pontos para obter tipo, nome, valor
// - Atualizar o campo apropriado diretamente através do ponteiro do map
// - Imprimir mensagem de atualização para cada operação
// TODO: Exibir o inventário atualizado
// Novamente, use o slice de ordem para uma saída consistente
// Calcular o valor total enquanto exibe
// TODO: Calcular e exibir o valor total do inventário
// Formato: "Total Inventory Value: $[total_value]"
}Esta lição inclui um quiz rápido. Comece a lição para respondê-lo e acompanhar seu progresso.
Todas as lições de Lógica & Fluxo
1Fluxo de Controle Avançado
Switch com `fallthrough`Interrompendo Loops AninhadosContinuando um Loop EspecíficoA Instrução `goto`Recapitulação - Controle de Loop Avançado4Projeto: Lista de Tarefas Simples
Configuração do ProjetoAdicionando uma Tarefa2Structs e Métodos
Definindo Métodos em StructsRecebedores de ValorRecebedores de PonteiroEscolhendo RecebedoresMétodos vs FunçõesRecapitulação - Comportamento de Structs5Mapas em Profundidade
Mapas de StructsPonteiros como Valores de MapVerificando Mapas NilComparando MapasRecapitulação - Contador de Frequência de Palavras3Interfaces (O Básico)
O que é uma Interface?Definindo uma InterfaceImplementando uma InterfaceUsando Tipos de InterfaceInterface VaziaAsserções de TipoType SwitchRecapitulação - Formas e Comportamentos