개요
Go maps in action 의 내용을 참고해서, Golang map기본 개념에 대해서 알아보겠습니다.
1. 기본 구조와 선언
1.1 map(맵)의 기본 구조
map[타입]값
map[KeyType]ValueType
- 타입: 비교 가능한 모든 타입이 올 수 있습니다.
- 값: 어떤 타입이든 올 수 있으며, 다른 맵도 포함될 수 있습니다.
1.2 map(맵) 변수 선언
문자열 키와 정수 값을 가지는 맵 변수를 선언하고 싶다면, 다음과 같이 표현 할 수 있습니다.
var m map[string]int
1.3 map(맵)의 특성
- map(맵)은 포인터나 슬라이스와 같은 참조 타입입니다.
- 위와 같이 선언만 한 맵 m의 값은 nil입니다.
- nil 맵은 읽을 때는 빈 맵처럼 동작하지만, 쓰기를 시도하면 런타임 패닉이 발생합니다.
1.4 map(맵) 초기화
map(맵)을 안전하게 사용하려면 반드시 초기화해야 합니다. 초기화에는 make 함수를 사용합니다.
m = make(map[string]int)
용량을 지정한 초기화
m := make(map[string]int, 100) // 초기 용량 100으로 설정
2. map(맵) 조작
2.1 map(맵)에 데이터 추가하기
map(맵)에 새로운 키-값 쌍을 추가하는 것은 간단합니다.
m["age"] = 99
2.2 map(맵)에서 데이터 검색하기
i := m["age"]
// 만약 "age" 키가 없다면, i == 0 (int 타입의 제로값)
키 존재 여부 확인과 함께 검색하고 싶을경우,
v, exists := m["age"]
- v: 키에 해당하는 값 (키가 없으면 제로값)
- exists: 키의 존재 여부를 나타내는 불리언 값 (있으면 true, 없으면 false)
예를들면,
m := map[string]int{"a": 0, "b": 1}
v1, exists1 := m["a"]
fmt.Printf("키 'a': 값 = %d, 존재 여부 = %v\n", v1, exists1)
// 출력: 키 'a': 값 = 0, 존재 여부 = true
v2, exists2 := m["c"]
fmt.Printf("키 'c': 값 = %d, 존재 여부 = %v\n", v2, exists2)
// 출력: 키 'c': 값 = 0, 존재 여부 = false
2.3 map(맵)의 크기 확인하기
내장 함수 len을 사용하여 map(맵)의 length를 확인할수 있습니다.
n := len(m)
2.4 map(맵)에서 항목 삭제하기
delete(m, "c")
delete 함수는 아무것도 반환하지 않으며, 지정된 키가 존재하지 않아도 오류를 발생시키지 않습니다.
2.5 map(맵) loop
for key, value := range m {
fmt.Println("Key:", key, "Value:", value)
}
3. 심화
3.1 map(맵)을 이용한 집합(Set) 구현
type void struct{}
var member void
set := make(map[string]void)
set["apple"] = member
set["banana"] = member
// 원소 존재 여부 확인
_, exists := set["apple"]
fmt.Printf("'apple'이 집합에 존재하나요? %v\n", exists)
3.2 중첩된 map(맵)
nestedMap := map[string]map[string]int{
"fruits": {
"apple": 5,
"banana": 3,
},
"vegetables": {
"carrot": 7,
"tomato": 4,
},
}
fmt.Printf("사과의 개수: %d\n", nestedMap["fruits"]["apple"])
3.3 map(맵)의 동시성 처리
sync.Map을 활용
import "sync"
var m sync.Map
// 저장
m.Store("key", "value")
// 검색
value, ok := m.Load("key")
if ok {
fmt.Printf("값: %v\n", value)
}
// 삭제
m.Delete("key")
// 순회
m.Range(func(key, value interface{}) bool {
fmt.Printf("키: %v, 값: %v\n", key, value)
return true
})
sync.RWMutex를 활용
var counter = struct{
sync.RWMutex
m map[string]int
}{m: make(map[string]int)}
// 읽기
counter.RLock()
n := counter.m["some_key"]
counter.RUnlock()
// 쓰기
counter.Lock()
counter.m["some_key"]++
counter.Unlock()
3.4 map(맵) 복사
original := map[string]int{"a": 1, "b": 2}
copied := make(map[string]int, len(original))
for k, v := range original {
copied[k] = v
}
참고
'프로그래밍 > Golang' 카테고리의 다른 글
Golang: 동일성(Identity) vs 동등성(Equality) (0) | 2024.08.03 |
---|---|
Golang 값을 전달할까, 포인터를 전달할까? (0) | 2024.08.02 |
Golang Slice(슬라이스) 요소 제거하기 (0) | 2024.07.31 |
Golang Slice(슬라이스) : make, copy, append (0) | 2024.07.31 |
Golang Arrays(배열), Slice(슬라이스) - 선언, 초기화 방법 (0) | 2024.07.31 |