マップはキーと値のペアの集まりで、それぞれの一意なキーが特定の値に対応します。
Goでマップを宣言するには、キーワードmapを使い、その後にキーと値の型を角括弧で囲みます。以下は、文字列をキー、整数を値とするマップを宣言する例です。
m := map[string]int{}
組み込みのmake関数を使って、マップを宣言することもできます。
m := make(map[string]int)
マップにキーと値のペアを追加するのは簡単です。角括弧の中のキーを使って、それに値を割り当てるだけです。
m["key"] = 10
マップから値を取り出すには、角括弧内のキーを利用できます。
value := m["key"]
キーがマップに存在しない場合、valueの値は、値の型に応じたゼロ値となります。キーがマップに存在するかどうかを確認するには、次の構文を使用します。
value, ok := m["key"]
変数okは、キーがマップに存在する場合はtrue、そうでない場合はfalseとなります。
それでは例を見てみましょう。
package main
import "fmt"
func main() {
// 文字列をキー、整数を値とするマップの宣言
m := map[string]int{
"John": 25,
"Jane": 30,
"Jim": 35,
}
// キー"Bob"がマップに存在するかどうかをチェック
value, ok := m["Bob"]
if ok {
fmt.Println("Value of Bob:", value)
} else {
fmt.Println("Key not found")
}
}
このコードは"Key not found"を出力します。キー"Bob"はマップmに存在しないので、ok変数はfalseになります。valueの値は0であり、これは整数型に対するゼロ値です。
マップからキーと値のペアを削除するには、delete関数を使用します。
delete(m, "key")
マップを繰り返し処理するには、forループとrangeキーワードを使用します。
for key, value := range m {
fmt.Println("Key:", key, "Value:", value)
}
マップはstruct型の値を格納するために使用することもできます。これは、関連するプロパティを持つオブジェクトのコレクションを、構造化された方法で保存および操作する場合に特に便利です。
例えば、nameやageなどのプロパティを持つPersonオブジェクトのコレクションを考えてみましょう。
package main
import "fmt"
func main() {
type Person struct {
name string
age int
}
people := make(map[string]Person)
people["John"] = Person{"John", 30}
people["Jane"] = Person{"Jane", 25}
for _, person := range people {
fmt.Println("Name:", person.name, "Age:", person.age)
}
}
マップを関数の引数として使用する例も見てみましょう。例えば、文字列と整数のマップを受け取り、すべての値の合計を返す関数を記述します。
package main
import "fmt"
func sumValues(m map[string]int) int {
sum := 0
for _, value := range m {
sum += value
}
return sum
}
func main() {
numbers := map[string]int{"one": 1, "two": 2, "three": 3}
sum := sumValues(numbers)
fmt.Println("The sum of the values is", sum)
}
デフォルトでは、Goのマップには保証された順序がありません。しかし、sortパッケージを使えば、マップのキーと値をソートすることができます。
キーをソートする例を見てみましょう。
package main
import (
"fmt"
"sort"
)
func main() {
numbers := map[string]int{"three": 3, "one": 1, "two": 2}
keys := make([]string, 0, len(numbers))
for key := range numbers {
keys = append(keys, key)
}
sort.Strings(keys)
for _, key := range keys {
fmt.Println(key, numbers[key])
}
}
値をソートする例を見てみましょう。
package main
import (
"fmt"
"sort"
)
func main() {
numbers := map[string]int{"three": 3, "one": 1, "two": 2}
values := make([]int, 0, len(numbers))
for _, value := range numbers {
values = append(values, value)
}
sort.Ints(values)
for _, value := range values {
for key, mapValue := range numbers {
if mapValue == value {
fmt.Println(key, value)
break
}
}
}
}
マップのゼロ値はnilです。nilマップはキーも値も持たず、make関数で適切に初期化されるまで使用することができません。
var m map[string]int
fmt.Println(m == nil) // true
一方、マップをmake関数を使って初期化した場合は、nilにはならない点に注意しましょう。make関数は、初期化された空のマップを返します。
m := make(map[string]int)
fmt.Println(m == nil) // false