
Mapについて学んでいきましょう。
Go言語のデータ構造として、これまでにArrayとSliceについて学んできました。
しかし、Go言語にはその他にもMapと呼ばれる重要なデータ構造があります。
本項では、Mapを学んでいきましょう。
<目次>
学習記事まとめ
Mapとは
Go言語には、ArrayやSliceの他に「Map」と呼ばれるデータ構造体が存在します。
Mapは、Key-Value型のコレクションで、Valueにアクセスする時は、Keyを使います。また、ArrayやSliceはindexに数値しか使えないのに対し、Mapではどのようなデータ型も使えます。
以下、Mapの宣言方法です。
1 2 3 4 |
var myMap map[keyType]<ValueType> 例) var myMap map[string]float64 |
また、Sliceと同様にmake関数で、Mapの実態を作成できます。
1 2 |
var myMap map[string]int // Map変数を宣言 myMap = make(map[string]int) // Map作成 |
または、Sliceと同様にshort variable declarationも使えます。
1 |
myMap := make(map[string]int) // Mapの作成と変数の宣言を同時に行う |
実際にコードで確認してみましょう。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
package main import "fmt" func main() { myMap := make(map[string]int) myMap["first"] = 1 myMap["second"] = 2 myMap["third"] = 3 fmt.Println(myMap) myMap2 := make(map[int]string) myMap2[1] = "first" myMap2[2] = "second" myMap2[3] = "third" fmt.Println(myMap2) } |
このサンプルコードを実行してみます。
1 2 3 |
$ go run main.go map[first:1 second:2 third:3] map[1:first 2:second 3:third] |
Mapリテラル
Mapは、変数宣言と同時に初期値を格納可能です。
1 2 3 4 |
myMap := map[string]float64{"a": 1.2, "b": 5.6} // 空を作りたい場合 myMap := map[string]float64{} |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
package main import "fmt" func main() { myMap := map[string]float64{ "point1": 1.2, "point2": 3.4, "point3": 5.6} fmt.Println(myMap["point1"]) fmt.Println(myMap["point2"]) fmt.Println(myMap["point3"]) } |
1 2 3 4 |
$ go run main.go 1.2 3.4 5.6 |
指定したKeyが存在しない場合
指定したKeyがMapに存在しない場合、どのような挙動を取るのでしょうか?

サンプルコードを書いて、ガンガン実証してみましょう!
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
package main import ( "fmt" ) func main() { numbers := make(map[string]int) numbers["You got a number"] = 7 // Key fmt.Printf("%#v\n", numbers["You got a number"]) // Not Key fmt.Printf("%#v\n", numbers["You didn't get a number"]) } |
実行します。
1 2 3 |
$ go run main.go 7 0 |
Keyがない場合はエラーにならず、「0」が取得されるようですね。
ちなみに「0」になったのは、MapのValueTypeがint型だったためです。

Go言語のtypeの初期値が出力されるようですね。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
package main import ( "fmt" ) func main() { numbers := make(map[string]bool) numbers["You got a number"] = true // Key fmt.Printf("%#v\n", numbers["You got a number"]) // Not Key fmt.Printf("%#v\n", numbers["You didn't get a number"]) } |
実行してみます。
1 2 3 |
$ go run main.go true false |
Mapの注意点
Sliceと同様にMapも初期化されていない場合は、nilになります。そして、宣言されているだけのMapに値を格納するとエラーが発生します。
実証してみましょう。
1 2 3 4 5 6 7 8 9 10 11 12 |
package main import ( "fmt" ) func main() { var m map[int]string fmt.Printf("%#v\n", m) m[3] = "three" } |
1 2 3 4 5 6 7 8 9 |
$ go run main.go map[int]string(nil) panic: assignment to entry in nil map goroutine 1 [running]: main.main() /Users/hoge/go/src/main.go:10 +0xae exit status 2 |

パニックが起こりましたね。KeyやValueを追加する前には必ずmakeかリテラルを使いましょう。
1 2 3 4 5 6 7 8 9 10 |
package main import "fmt" func main() { // Need to create a map fast var m map[int]string = make(map[int]string) m[3] = "three" fmt.Printf("%#v\n", m) } |
1 2 3 |
$ go run main.go map[int]string{3:"three"} |
変数「ok」
Mapの第二引数には、bool値を返すようになっています。この値を受け取る際、Goの開発者は変数に「ok」と名付けるそうです(明確な名前かつ短いため)。
1 2 3 4 5 6 7 8 9 10 11 12 13 |
package main import "fmt" func main() { myArray := map[string]int{"a": 1, "b": 2} value, ok := myArray["a"] fmt.Println(value, ok) value, ok = myArray["b"] fmt.Println(value, ok) value, ok = myArray["c"] fmt.Println(value, ok) } |
1 2 3 4 5 |
$ go run main.go 1 true 2 true 0 false |
Map削除
次は、Mapの値を削除する方法について見ていきましょう。
Go言語では、delete関数を提供しており、 この関数がその役割を担います。
1 2 3 4 5 6 7 8 9 10 11 12 |
package main import "fmt" func main() { myArray := map[string]int{"apple": 10, "banana": 20, "cake": 30} food, ok := myArray["apple"] fmt.Printf("myArray: %d, ok: %v\n", food, ok) delete(myArray, "apple") food, ok = myArray["apple"] fmt.Printf("myArray: %d, ok: %v\n", food, ok) } |
1 2 3 4 |
$ go run main.go myArray: 10, ok: true myArray: 0, ok: false |
簡単ですね。
やってみよう1
プログラミング学習は、アプトプットが大切です。
次のアプリケーションを作成してみましょう。
1. names.txtを読み取る
2. names.txtに書き込まれた名前をカウントする
3. カウントの結果をterminal上に出力する
4. Mapを利用する
端的に言うと、ファイルの中に同名の名前がいくつ記載されているのか調べるプログラムです。
names.txtの中身は、こんな感じです。
1 2 3 4 5 6 7 8 |
James Harry Ron Bob Mary Harry Bob James |
それでは、早速作りましょう。サンプルプログラムを載せておきます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 |
package main import ( "bufio" "fmt" "log" "os" ) func getStrings(fileName string) ([]string, error) { var lines []string file, err := os.Open(fileName) if err != nil { return nil, err } scanner := bufio.NewScanner(file) for scanner.Scan() { line := scanner.Text() lines = append(lines, line) } err = file.Close() if err != nil { return nil, err } if scanner.Err() != nil { return nil, scanner.Err() } return lines, nil } func main() { names, err := getStrings("names.txt") if err != nil { log.Fatal(err) } counts := make(map[string]int) for _, name := range names { counts[name]++ } fmt.Println(counts) } |
実行してみましょう。
1 2 3 |
$ go run main.go map[Bob:2 Harry:2 James:2 Mary:1 Ron:1] |
Mapのループ
ArrayやSliceと同様に、Mapもfor…rangeが使えます。
1 2 3 |
for key, value := range myMap { // Loop block here. } |
サンプルはこちらです。
1 2 3 4 5 6 7 8 9 10 |
package main import "fmt" func main() { foods := map[string]int{"Apple": 10, "Banana": 20, "Cake": 30} for food, num := range foods { fmt.Printf("%s has a price of %d$\n", food, num) } } |
1 2 3 4 5 6 |
$ go run main.go Apple has a price of 10$ Banana has a price of 20$ Cake has a price of 30$ |
簡単ですね。ちなみに、Mapは、Keyの順番が保証されていないコレクションになります。何回かプログラムを実行してみましょう。
1 2 3 4 5 6 7 8 9 10 11 |
$ go run main.go Cake has a price of 30$ Apple has a price of 10$ Banana has a price of 20$ $ go run main.go Apple has a price of 10$ Banana has a price of 20$ Cake has a price of 30$ |

これが結構バグになりやすいです。気をつけてください。
sortパッケージのStrings関数を使うとソートができます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
package main import ( "fmt" "sort" ) func main() { foods := map[string]int{"Banana": 20, "Cake": 30, "Apple": 10} var names []string for food := range foods { names = append(names, food) } sort.Strings(names) for _, name := range names { fmt.Printf("%s has a grade of %d$\n", name, foods[name]) } } |
1 2 3 4 5 |
$ go run main.go Apple has a grade of 10$ Banana has a grade of 20$ Cake has a grade of 30$ |
まとめ

最後にこの章で学んだことをまとめておきましょう。
・ mapキーワードで、Mapを宣言する -> var myMap map[string]int
・ makeキーワードで、Mapを作成する -> myMap = make(map[string]int)
・ mapは、key-valueタイプのデータ構造隊 -> myMap[“key”] = value
・ mapの値はkeyでアクセスする -> fmt.Println(myMap[“key”])
・ Mapリテラルで、作成&初期化ができる -> map[string]int{“a”: 1, “b”: 2}
・ Map内に存在しない要素へアクセスした場合は、基底になったtypeの初期値を返す
・ Mapの2番目の戻り値はbool値であり、ok変数で受け取るとGood
・ Mapの要素を削除したい場合は、delete関数を使用する
・ for…rangeでMapの要素を一気に出力することができる
次回
次回は、Sliceについて学んでいきます。
コメントを残す
コメントを投稿するにはログインしてください。