이 글은 Effective Go를 일부 번역한 글입니다.


자료

맵은 편리하고 강력한 내장 자료 구조로, 한 유형의 값(열쇠)을 다른 유형의 값(요소, 값)에 연결한다. 열쇠는 상등 연산자를 정의한 어떤 유형이든 가능하다. 즉, 정수, 실수, 복소수, 문자열, 포인터, 인터페이스(동적 유형이 상등성을 지원해야 한다), 구조체, 배열 등이 가능하다. 조각은 맵 열쇠로 사용할 수 없다. 상등성을 정의하지 않았기 때문이다. 맵도 조각처럼 기반 자료 구조를 참조한다. 맵을 함수에 보내 내용을 바꾼다면 그 변화를 호출자가 볼 수 있다.

맵은 열쇠와 값을 쌍점으로 구분하고 나열해 혼합 리터럴 형식으로 만들 수 있어 쉽게 초기화 중에 만들 수 있다.

var timeZone = map[string]int{
    "UTC":  0*60*60,
    "EST": -5*60*60,
    "CST": -6*60*60,
    "MST": -7*60*60,
    "PST": -8*60*60,
}

맵에 값을 할당하고 불러오는 건 색인을 정수로 넣을 필요가 없다는 걸 제외하면 문장상 배열이나 조각에 같은 걸 하는 것처럼 보인다.

offset := timeZone["EST"]

맵에 없는 열쇠로 값을 찾으면 맵이 담은 유형의 0 값을 반환한다. 예로, 정수를 담은 맵에 없는 열쇠로 값을 찾으면 0을 반환한다. 묶음(Set)은 맵 값 유형을 bool로 하면 구현할 수 있다. 맵 값을 true로 해 묶음에 넣고 단순히 찾아 보면 된다.

attended := map[string]bool{
    "Ann": true,
    "Joe": true,
    ...
}

if attended[person] { // will be false if person is not in the map
    fmt.Println(person, "was at the meeting")
}

가끔 0 값이 항목이 없어 나온 건지 구별할 필요가 있다. “UTC” 항목이 있는가, 아니면 맵에 없어서 빈 문자열이 나왔는가? 다중 할당 형식으로 구별하면 된다.

var seconds int
var ok bool
seconds, ok = timeZone[tz]

명백한 이유로 이를 “반점 ok” 양식이라 부른다. 이 예에서 tz가 있으면 seconds는 알맞게, ok는 참으로 설정된다. 없다면 seconds는 0으로, ok는 거짓으로 설정된다. 아래 함수는 여기에 친절한 오류 보고를 더했다.

func offset(tz string) int {
    if seconds, ok := timeZone[tz]; ok {
        return seconds
    }
    log.Println("unknown time zone:", tz)
    return 0
}

실제 값을 고려하지 않고 존재 여부만 확인하려면 공백 식별자(_)를 값 변수 자리에 둔다.

_, present := timeZone[tz]

맵 항목을 제거하려면 delete 내장 함수를 사용하라. 인수로 맵과 지울 열쇠를 넣는다. 열쇠가 이미 맵에 없어도 안전하다.

delete(timeZone, "PDT")  // Now on Standard Time