マップ

Go のマップは Ruby でいうハッシュ、Python の辞書、要するに連想配列だ。
マップの宣言、初期化は例を見たほうが早いだろう。次のようにする。

package main

import "fmt"

func main() {
    var a map[string]int
    var b map[string]int = map[string]int{ "foo": 1, "bar": 2 }
    var c = map[string]int{ "hoge": 10, "fuga": 20 }

    fmt.Println(a)
    fmt.Println(b)
    fmt.Println(c)
}
^o^ > go run map.go
map[]
map[foo:1 bar:2]
map[hoge:10 fuga:20]

ここで注意。上の例の変数 a のように宣言だけして初期化をしないと、nilマップというものになる。これは空のマップとは違って、キーの追加とかができない。試してみよう。

package main

import "fmt"

func main() {
    var a map[string]int

    fmt.Println(a)

    a["hoge"] = 100

    fmt.Println(a)
}
^o^ > go run map2.go
map[]
panic: assignment to entry in nil map

goroutine 1 [running]:
main.main()
        C:/Users/takatoh/Documents/w/learning-go/map2.go:10 +0xa7
exit status 2

この通り、a["hoge"] = 100 のところでエラーを起こしている。なんでこんな仕様になってるんだろ?
で、空のマップがほしい時には make 関数を使う。

package main

import "fmt"

func main() {
    var a = make(map[string]int)

    fmt.Println(a)

    a["foo"] = 10
    a["bar"] = 20

    fmt.Println(a)
}

これなら新しいキー(と値)を追加できる。

^o^ > go run map3.go
map[]
map[foo:10 bar:20]

参照するには [] でキーを指定すればいいけど、返ってくる値は2つある。キーが存在する場合には対応する値と true が、存在しない場合にはゼロ値と false が返ってくる。これはつまり Go には多値があるってことだけど、これについては別の機会に書く。
ともかく、キーが存在するかどうかは2つ目の返り値を見ないとわからないので、ちょっと面倒。
あと、キー(と値)を削除するには delete 関数を使う。

package main

import "fmt"

func main() {
    a := map[string]int{ "foo": 1, "bar": 2 }

    fmt.Println(a)

    value, ok := a["foo"]
    if ok {
        fmt.Println(value)
    }

    a["baz"] = 3
    delete(a, "bar")

    fmt.Println(a)
}
^o^ > go run map4.go
map[foo:1 bar:2]
1
map[baz:3 foo:1]