본문 바로가기
golang (go)

golang map

by first author 2023. 12. 24.
728x90
반응형

Go Map

Introduction

Golang 에서 map은 Hash table을 기반으로 구현되어있다.
이에 빠른 검색, 추가, 삭제를 특징으로 한다. Hash Table 기본적으로 Hash Collision이 없다는 전재하에 Olog1의 매우 빠른 검색 속도를 제공한다.

Go에서 구현한 Map에 대한 설명, 그리고 Hash Table에 대한 상세한 설명은 아래 블로그를 추천하니 상세히 읽어보면 많은 도움이 될 것이다.

Go에서 제공하는 map은 Hash Table을 구현한 타입으로 소개하고 있다.

Go map 사용법

map structure (구조)

Go의 map은 아래와 같이 key : value 타입으로 구성되어있다. 여기서 key의 type과 value의 type은 다른 map을 포함하는 any type이 될 수 있다.

map\[Key\]ValueType

단 key type은 comparable operators (비교 연산자)를 지원해야 한다.

==    equal
!=    not equal
<     less
<=    less or equal
>     greater
>=    greater or equal

map declaration (선언)

map을 생성할 때는 아래와 같이 var 변수로 선언할 수 있으며 key와 value의 type을 지정해야한다.

var m map[string]int

go에서 제공하는 map은 pointer나 slices와 같이 reference type이다. 그래서 map의 초기 기본 값은 nil로 정의되어있다.

때문에 선언만하고 초기화를 하지 않은 map을 읽으면 아래오 같이 nil로 처리가 된다.

  • map 선언 예제
func main() {
	var fruitsColorMap map[string]string

	fmt.Println("fruitsColorMap:", fruitsColorMap)
	if fruitsColorMap == nil {
    	fmt.Println("fruitsColorMap is nil")
	} else {
    	fmt.Println("fruitsColorMap is initialized")
	}
}
  • 실행결과
$go run main.go
fruitsColorMap: map[]
fruitsColorMap is nil

 

만약 초기화를 하지 않고 write(쓰기)를 수행하는 경우 아래와 같이 runtime panic 에러가 발생하게 되니 사용 전에 반드시 초기화하는 것을 잊으면 안된다.

  • map 선언 후 초기화 하지 않고 쓰기 시도 예제
var fruitsColorMap map[string]string
fruitsColorMap["apple"] = "red"
  • 실행 결과
$go run main.go
panic: assignment to entry in nil map

goroutine 1 [running]:
main.main()
/Users/wise.kim/github/github.com/HyunWookKim/golang-map-first/main.go:6 +0x34
exit status 2

map initialization (초기화)

map은 아래와 같이 make 함수를 이용하여 생성하거나, {}를 이용하여 빈값으로 초기화 해줄 수 있다.

  • 방법 1 - make function을 map 초기화
var fruitsColorMap map[string]string
fruitsColorMap = make(map[string]string)
  • 방법 2 - literal{}을 이용한 map 초기화
var fruitsColorMap map[string]string
fruitsColorMap = map[string]string{}

map write (쓰기)

map에서는 아래와 같이 key와 value 의 type에 맞추어 값을 쓸 수 있다. 만약 동일한 key로 여러번 write를 시도하면 마지막에 쓴 값이 write 된다.

var fruitsColorMap map[string]string
fruitsColorMap = make(map[string]string)

fruitsColorMap["apple"] = "red"
fruitsColorMap["banana"] = "yellow"

 

map read (읽기)

map에 저장한 값은 key 를 지정하여 읽을 수 있다. 만약 없는 key로 요청한다면 value type의 default 값을 리턴해주게 된다.

 

  • map 쓰고 읽기 예제
func main() {
	var fruitsColorMap map[string]string

	fruitsColorMap = make(map[string]string)

	fruitsColorMap["apple"] = "red"
	fruitsColorMap["banana"] = "yellow"

	fmt.Println("apple color:", fruitsColorMap["apple"])
	fmt.Println("melon color:", fruitsColorMap["melon"])	// 없는 키로 읽기 시도
}

 

  • 실행 결과
go run main.go                                                                                                                                                      14:12:49 
apple color: red
melon color:

 

만약 조회하려는 key가 있는 값인지 사전에 전처리를 하고 싶다면 아래와 같이 boolean 타입의 리턴값을 받는 변수를 추가하면 된다.

만약 key 값이 존재한다면 true를 반환하고, 없다면 false를 반환한다.

 

  • map에 key 값이 존재하는지 유무 확인 예제
func main() {
	var fruitsColorMap map[string]string

	fruitsColorMap = make(map[string]string)

	fruitsColorMap["apple"] = "red"
	fruitsColorMap["banana"] = "yellow"

	melonColor, ok := fruitsColorMap["melon"]
	fmt.Println("is exist key(melon)? ", ok)
	if ok {
		fmt.Println("melon color:", melonColor)
	}

	appleColor, ok := fruitsColorMap["apple"]
	fmt.Println("is exist key(apple)? ", ok)
	if ok {
		fmt.Println("apple color:", appleColor)
	}
}
  • 실행 결과
$ go run main.go                                                                                                                                                      14:36:40 
is exist key(melon)?  false
is exist key(apple)?  true
apple color: red
반응형

map length (크기 구하기)

map의 크기는 len() function 을 이용하여 구할 수 있다.

 

  • len()을 이용한 map 크기 구하기 예제
func main() {
	var fruitsColorMap map[string]string

	fruitsColorMap = make(map[string]string)

	fruitsColorMap["apple"] = "red"
	fruitsColorMap["banana"] = "yellow"
	fruitsColorMap["strawberry"] = "red"
	fruitsColorMap["grape"] = "purple"
	fruitsColorMap["avocado"] = "green"
	fruitsColorMap["blueberry"] = "blue"
	fruitsColorMap["cherry"] = "red"
	fruitsColorMap["kiwi"] = "green"

	fmt.Println("fruitsColorMap Size:", len(fruitsColorMap))
}

 

  • 실행 결과
$ go run main.go
fruitsColorMap Size: 8

map delete (element  삭제)

map 의 key와 value를 지우기 위해서는 아래와 같이 delete() 함수를 사용한다.

func delete(m map[Type]Type1, key Type)

 

delete 함수의 첫 번째 인자로 element를 삭제하고자 하는 map을 전달하고, 두 번째 인자에 지우고자 하는 element의 key 값을 입력하면 된다. 만약 해당 key 값이 존재하지 않는다면 아무 일도 발생하지 않는다.

  • map delete 예제
func main() {
	var fruitsColorMap map[string]string

	fruitsColorMap = make(map[string]string)

	fruitsColorMap["apple"] = "red"
	fruitsColorMap["banana"] = "yellow"
	fruitsColorMap["strawberry"] = "red"
	fruitsColorMap["grape"] = "purple"
	fruitsColorMap["avocado"] = "green"
	fruitsColorMap["blueberry"] = "blue"
	fruitsColorMap["cherry"] = "red"
	fruitsColorMap["kiwi"] = "green"

	fmt.Printf("fruitsColorMap[%s]: %s\n", "apple", fruitsColorMap["apple"])
	delete(fruitsColorMap, "apple")	//"apple" 키를 갖는 element 삭제.
	delete(fruitsColorMap, "melon")	// 존재하지 않는 키로 맵 element 삭제. 아무일도 없음
	fmt.Printf("fruitsColorMap[%s]: %s\n", "apple", fruitsColorMap["apple"])
}

 

  • map delete 예제 결과
$ go run main.go
fruitsColorMap[apple]: red
fruitsColorMap[apple]:

 

지금까지 golang에서 built-in 으로 제공하는 hash table을 구현한 map의 사용법을 알아보았습니다.

map은 정말 많은 상황에서 사용되지만 치명적인 단점이 있습니다. 바로 Multi-Thread 방식에 Safety 하지 않다는 것이죠. 

다음 시간에는 map을 Multi-Thread 방삭에서도 안전하게 사용할 수 있는 방법을 소개해드리도록 하겠습니다.

 

감사합니다.

728x90
반응형

댓글