フリーキーズ | 独学プログラミング

Go言語のMapを初心者向けに解説!作り方からキー操作まで実例で学ぶ

リンドくん

リンドくん

たなべ先生、Go言語を勉強してるんですけど、Mapってよくわからないんです。配列とは何が違うんですか?

たなべ

たなべ

Mapはキーと値をペアで管理できるデータ構造なんだ。
例えば、「名前」をキーにして「年齢」を値として管理したり、「商品名」から「価格」を調べたりできるんだよ。

プログラミングを学んでいると、データを効率的に管理する方法について悩むことがありませんか?
特にGo言語を始めたばかりの方にとって、Mapという概念は少し理解が難しいかもしれません。

しかし、Mapを理解すると、プログラミングの幅が大きく広がります。
データベースのような複雑な構造を持つデータを、シンプルかつ効率的に操作できるようになるからです。

この記事では、Go言語のMapについて、基本的な概念から実践的な使い方まで、初心者の方でも理解できるよう段階的に解説していきます。

プログラミング学習でお悩みの方へ

HackATAは、エンジニアを目指す方のためのプログラミング学習コーチングサービスです。 経験豊富な現役エンジニアがあなたの学習をサポートします。

✓ 質問し放題

✓ β版公開中(2025年内の特別割引)

HackATAの詳細を見る

Mapとは何か?基本概念を理解しよう

リンドくん

リンドくん

そもそもMapって、なんで「Map」という名前なんですか?

たなべ

たなべ

「Map」は地図という意味もあるけど、プログラミングでは「対応付け」や「写像」という意味なんだ。
つまり、あるキーに対して特定の値を対応付けるデータ構造だからMap(マップ)と呼ばれているんだよ。

Mapの基本的な仕組み

Mapは、キー(Key)と値(Value)をペアで管理するデータ構造です。
他の言語では「ハッシュマップ」や「辞書」と呼ばれることもあります。

配列が数字のインデックス(0, 1, 2...)で要素にアクセスするのに対し、Mapは任意のキーで値にアクセスできます。

例えば、以下のような対応関係を管理できます。

  • 「apple」→ 100(商品名と価格)
  • 「tanabe」→ 36(名前と年齢)
  • 「Tokyo」→ 1400万(都市名と人口)

配列との違い

配列とMapの違いを具体的に見てみましょう。

配列の場合

fruits := []string{"apple", "banana", "orange"}
// インデックス 0 で "apple" を取得
fmt.Println(fruits[0]) // "apple"

Mapの場合

prices := map[string]int{
    "apple":  100,
    "banana": 80,
    "orange": 120,
}
// キー "apple" で価格を取得
fmt.Println(prices["apple"]) // 100

このように、Mapは意味のあるキーを使ってデータにアクセスできるため、より直感的で読みやすいコードが書けるのです。

Mapの作成方法とデータ型の指定

基本的な作成方法

Go言語では、Mapを作成する方法がいくつかあります。最も基本的な書き方から見ていきましょう。

1. リテラル記法による作成

// 文字列をキー、整数を値とするMap
studentScores := map[string]int{
    "Tanabe": 85,
    "Tanaka": 92,
    "Takahashi": 78,
}

2. make関数による作成

// 空のMapを作成
studentScores := make(map[string]int)

// 後から値を設定
studentScores["Tanabe"] = 85
studentScores["Yoshida"] = 92

3. var宣言による作成

var studentScores map[string]int
// 注意:この時点ではnilなので、使用前にmakeが必要
studentScores = make(map[string]int)

データ型の指定方法

Mapのデータ型はmap[キーの型]値の型という形式で指定します。

// よく使われるパターン
var userAges map[string]int        // 文字列 → 整数
var itemPrices map[string]float64  // 文字列 → 小数
var settings map[string]bool       // 文字列 → 真偽値
var coordinates map[string][2]int  // 文字列 → 配列

実用的な例

実際のプログラムでよく使われるパターンを見てみましょう。

package main

import "fmt"

func main() {
    // ユーザー情報を管理するMap
    userInfo := map[string]string{
        "name":  "田辺太郎",
        "email": "tanabe@example.com",
        "role":  "instructor",
    }
    
    // 商品在庫を管理するMap
    inventory := make(map[string]int)
    inventory["laptop"] = 10
    inventory["mouse"] = 25
    inventory["keyboard"] = 15
    
    fmt.Println("ユーザー名:", userInfo["name"])
    fmt.Println("ラップトップ在庫:", inventory["laptop"])
}

このように、Mapを使うことで関連するデータを効率的に管理できます。

要素の追加・更新・削除操作

リンドくん

リンドくん

Mapに新しいデータを追加したり、既存のデータを変更したりするにはどうすればいいんですか?

たなべ

たなべ

それが実はとてもシンプルなんだ!代入演算子(=)を使うだけで追加も更新もできるよ。
削除には特別なdelete関数を使うんだ。

要素の追加と更新

Mapでは、新しいキーに値を代入すると追加、既存のキーに値を代入すると更新になります。

package main

import "fmt"

func main() {
    // 空のMapを作成
    scores := make(map[string]int)
    
    // 要素の追加
    scores["Tanabe"] = 85
    scores["Yoshida"] = 92
    fmt.Println("追加後:", scores) // map[Tanabe:85 Yoshida:92]
    
    // 要素の更新(既存のキーに新しい値を代入)
    scores["Tanabe"] = 88
    fmt.Println("更新後:", scores) // map[Tanabe:88 Yoshida:92]
    
    // さらに要素を追加
    scores["Shimamoto"] = 95
    fmt.Println("最終:", scores) // map[Tanabe:88 Yoshida:92 Shimamoto:95]
}

要素の削除

要素を削除するにはdelete関数を使用します。

package main

import "fmt"

func main() {
    prices := map[string]int{
        "apple":  100,
        "banana": 80,
        "orange": 120,
    }
    
    fmt.Println("削除前:", prices) // map[apple:100 banana:80 orange:120]
    
    // "banana"を削除
    delete(prices, "banana")
    fmt.Println("削除後:", prices) // map[apple:100 orange:120]
    
    // 存在しないキーを削除してもエラーにならない
    delete(prices, "grape") // 何も起こらない
    fmt.Println("存在しないキー削除後:", prices) // map[apple:100 orange:120]
}

このように、Mapの操作は非常にシンプルで直感的です。追加・更新・削除の基本操作をマスターすれば、様々なデータ管理ができるようになります。

キーの存在確認と安全なアクセス方法

キーの存在確認が重要な理由

Mapで存在しないキーにアクセスすると、ゼロ値が返されます。これが問題となる場合があります。

scores := map[string]int{
    "Tanabe": 85,
    "Yoshida": 92,
}

fmt.Println(scores["Tanabe"])    // 85(存在する)
fmt.Println(scores["Shimamoto"]) // 0(存在しないためゼロ値)

「Shimamoto」の点数が本当に0点なのか、それとも存在しないだけなのかが区別できません。

カンマok記法による安全なアクセス

Go言語では「カンマok記法」を使って、キーの存在を確認できます。

package main

import "fmt"

func main() {
    scores := map[string]int{
        "Tanabe": 85,
        "Yoshida":   92,
        "Miyama": 0, // 実際に0点
    }
    
    // 存在するキー
    if score, exists := scores["Tanabe"]; exists {
        fmt.Printf("Tanabeの点数: %d\n", score) // Tanabeの点数: 85
    } else {
        fmt.Println("Tanabeのデータは存在しません")
    }
    
    // 存在しないキー
    if score, exists := scores["Shimamoto"]; exists {
        fmt.Printf("Shimamotoの点数: %d\n", score)
    } else {
        fmt.Println("Shimamotoのデータは存在しません") // こちらが出力される
    }
    
    // 存在するが値が0のキー
    if score, exists := scores["Miyama"]; exists {
        fmt.Printf("Miyamaの点数: %d(存在する)\n", score) // Miyamaの点数: 0(存在する)
    } else {
        fmt.Println("Miyamaのデータは存在しません")
    }
}

このように、カンマok記法を使うことで、より安全で予測可能なコードが書けるようになります。

ベストプラクティス

  1. ゼロ値の初期化: make(map[type]type)を使って初期化する
  2. 存在確認: 重要な処理では必ずカンマok記法を使用する
  3. 適切な型選択: キーには比較可能な型(文字列、数値、配列など)を使用する
  4. 並行安全性: 複数のgoroutineからアクセスする場合はsync.Mapsync.RWMutexを検討する

これらの例を参考に、自分のプログラムでもMapを積極的に活用してみてください。

まとめ

リンドくん

リンドくん

Mapって思った以上に便利ですね!

たなべ

たなべ

そうだね!Mapを使いこなせると、効率的で読みやすいコードが書けるようになるよ。
最初は基本操作から始めて、徐々に応用的な使い方にチャレンジしてみてね。

この記事では、Go言語のMapについて基本概念から実践的な活用法まで解説してきました。

重要なポイントをおさらいしましょう。

  • Mapはキーと値をペアで管理する効率的なデータ構造
  • 作成方法は複数あるが、make(map[キー型]値型)が基本
  • 要素の追加・更新は代入演算子削除はdelete関数を使用
  • カンマok記法でキーの存在を安全に確認できる

Mapは現代のプログラミングにおいて必須のデータ構造です。
特に、大量のデータを効率的に管理したり、関連性のあるデータをグループ化したりする際に、その真価を発揮します。

次のステップとして、実際にサンプルコードを動かしてみることをお勧めします。
自分で様々なパターンを試すことで、Mapの理解がより深まるはずです。

この記事をシェア

関連するコンテンツ