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자리까지 형식을 맞춥니다. 이 챌린지는 맵에 포인터를 저장함으로써 맵에 값을 다시 할당할 필요 없이 원본 구조체 데이터를 직접 수정하여 재고 업데이트를 즉각적이고 영구적으로 만드는 방법을 보여줍니다.
치트 시트
맵은 구조체에 대한 포인터를 저장할 수 있어, 맵을 통해 원래 구조체 데이터를 직접 수정할 수 있습니다:
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이 패턴은 맵이 기본 데이터 저장소 역할을 하는 재고 시스템이나 사용자 프로필과 같이 빈번한 데이터 업데이트가 필요한 애플리케이션에 유용합니다.
직접 해보기
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]"
}이 레슨에는 짧은 퀴즈가 포함되어 있습니다. 레슨을 시작해 문제를 풀고 진행 상황을 기록하세요.