Map 값으로 포인터 사용하기
Coddy GO 여정의 로직 & 흐름 섹션에 포함된 레슨 — 68개 중 27번째.
구조체를 맵에 직접 저장하는 것도 유용하지만, 구조체에 대한 포인터를 저장하면 강력한 기능을 활용할 수 있습니다. 바로 맵을 통해 원본 구조체 데이터를 직접 수정할 수 있는 기능입니다. 이 방식은 데이터를 저장한 후에 업데이트해야 할 때 필수적입니다.
구조체에 대한 포인터를 맵의 값으로 저장할 때, 구조체의 복사본이 아니라 구조체의 메모리 주소를 저장하는 것입니다. 이러한 맵을 선언하고 사용하는 방법은 다음과 같습니다:
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},
}데이터를 수정해야 할 때 주요 장점이 명확해집니다. 포인터를 사용하고 있기 때문에, 맵을 통해 변경한 사항이 원래의 구조체에 영향을 미칩니다:
// 맵을 통해 직접 노트북의 가격을 업데이트합니다
products["laptop"].Price = 899.99
fmt.Println(products["laptop"].Price) // 출력: 899.99이 패턴은 재고 시스템, 사용자 프로필 또는 맵이 기본 데이터 저장소 역할을 하고 수정 사항이 유지되어야 하는 시나리오와 같이, 저장된 데이터를 빈번하게 업데이트해야 하는 애플리케이션에서 특히 유용합니다.
챌린지
쉬움구조체 포인터를 맵의 값으로 사용하는 강력한 기능을 보여주는 간단한 재고 관리 시스템을 구축해 보세요. 이 챌린지는 포인터 기반 맵이 저장된 데이터를 직접 수정할 수 있게 하여, 재고 시스템을 효율적이고 업데이트에 민첩하게 만드는 방법을 보여줍니다.
세 가지 입력을 받게 됩니다:
- 제품 수를 나타내는 문자열 (예:
"4") "name1:price1:quantity1,name2:price2:quantity2,name3:price3:quantity3"형식의 제품 데이터를 포함하는 문자열 (예:"laptop:999.99:5,mouse:25.50:20,keyboard:75.00:15,monitor:299.99:8")"operation1:product1:value1,operation2:product2:value2"형식의 업데이트 작업을 포함하는 문자열. 여기서 작업은"price"또는"quantity"중 하나입니다 (예:"price:laptop:899.99,quantity:mouse:25,price:keyboard:65.00")
여러분의 과제는 다음과 같습니다:
- 다음 필드를 가진
Product구조체를 정의합니다:Price(float64) - 제품 가격Quantity(int) - 제품 재고 수량
- 키는 제품 이름(문자열)이고 값은
Product구조체에 대한 포인터인 맵을 생성합니다. - 두 번째 입력에서 제품 데이터를 파싱합니다:
- 입력을 쉼표로 나누어 개별 제품 항목을 가져옵니다.
- 각 항목을 콜론으로 나누어 이름, 가격, 수량을 분리합니다.
- 가격 문자열을 float64로, 수량 문자열을 정수로 변환합니다.
Product구조체를 생성하고 맵에 해당 구조체의 포인터를 저장합니다.
"Initial Inventory:"라는 헤더와 함께 초기 재고를 표시합니다.- 각 제품을
"[name]: $[price] (Stock: [quantity])"형식으로 표시합니다. - 세 번째 입력에서 업데이트 작업을 파싱하고 적용합니다:
- 입력을 쉼표로 나누어 개별 작업을 가져옵니다.
- 각 작업을 콜론으로 나누어 작업 유형, 제품 이름, 새 값을 가져옵니다.
- 맵 포인터를 통해 해당 필드를 직접 업데이트합니다.
- 각 업데이트를
"Updated [product]: [field] changed to [new_value]"형식으로 출력합니다.
"Updated Inventory:"라는 헤더와 함께 업데이트된 재고를 표시합니다.- 초기 표시와 동일한 형식으로 각 제품을 다시 표시합니다.
- 총 재고 가치를 계산하고 표시합니다:
"Total Inventory Value: $[total_value]"
가격 및 수량 문자열을 각각의 숫자 유형으로 변환하려면 strconv 패키지를 사용하세요. 표시할 때 모든 가격은 소수점 이하 2자리까지 형식을 맞춥니다. 이 챌린지는 맵에 포인터를 저장함으로써 맵에 값을 다시 할당할 필요 없이 원본 구조체 데이터를 직접 수정하여 재고 업데이트를 즉각적이고 영구적으로 만드는 방법을 보여줍니다.
직접 해보기
package main
import (
"fmt"
"strconv"
"strings"
)
func main() {
// 입력 읽기
var numProductsStr string
var productDataStr string
var operationsStr string
fmt.Scanln(&numProductsStr)
fmt.Scanln(&productDataStr)
fmt.Scanln(&operationsStr)
// TODO: 여기에 Product 구조체 정의
// TODO: 제품 포인터를 저장할 맵 생성
// TODO: 제품 순서를 유지하기 위한 슬라이스 생성 (일관된 출력을 보장하기 위함)
// TODO: 제품 데이터를 파싱하고 맵에 채우기
// 기억할 사항:
// - productDataStr를 쉼표로 분할하여 개별 항목 가져오기
// - 각 항목을 콜론으로 분할하여 이름, 가격, 수량 가져오기
// - 가격 및 수량 문자열을 적절한 타입으로 변환
// - 맵에 Product 구조체 포인터 저장
// - 순서 슬라이스에 제품 이름 추가
// TODO: 초기 재고 표시
// 순서 슬라이스를 사용하여 제품을 일관되게 반복
// 형식: "[name]: $[price] (Stock: [quantity])"
// TODO: 업데이트 작업 파싱 및 적용
// 기억할 사항:
// - operationsStr를 쉼표로 분할하여 개별 작업 가져오기
// - 각 작업을 콜론으로 분할하여 유형, 이름, 값 가져오기
// - 맵 포인터를 통해 해당 필드를 직접 업데이트
// - 각 작업에 대한 업데이트 메시지 출력
// TODO: 업데이트된 재고 표시
// 다시 한 번, 일관된 출력을 위해 순서 슬라이스 사용
// 표시하면서 총 가치 계산
// TODO: 총 재고 가치 계산 및 표시
// 형식: "Total Inventory Value: $[total_value]"
}이 레슨에는 짧은 퀴즈가 포함되어 있습니다. 레슨을 시작해 문제를 풀고 진행 상황을 기록하세요.