最新のプログラミング言語のほとんどには、_dictionary_または_hash_タイプの概念があります。 これらのタイプは一般に、*値*にマップされる*キー*とペアでデータを保存するために使用されます。

Goでは、_map_データ型はほとんどのプログラマーが_dictionary_型と考えるものです。 キーに値をマップし、Goにデータを保存する便利な方法であるキーと値のペアを作成します。 マップは、キーワード `+ map `の後に角括弧で囲まれたキーデータ型 ` [] +`が続き、その後に値データ型が続くことで構築されます。 次に、キーと値のペアは、どちらかの側の波括弧の中に配置されます\ {}:

map[]{}

通常、Goでマップを使用して、IDに含まれる情報などの関連データを保持します。 データを含むマップは次のようになります。

map[string]string{"name": "Sammy", "animal": "shark", "color": "blue", "location": "ocean"}

中括弧に加えて、キーと値のペアを接続するコロンがマップ全体にあります。 コロンの左側の単語がキーです。 キーには、Goの任意の_comparable_タイプ( + strings +、 `+ ints +`など)を使用できます。

マップ例のキーは次のとおりです。

  • " name "

  • "動物 "

  • "色 "

  • " location "

コロンの右側の単語は値です。 値は任意のデータ型にすることができます。 サンプルマップの値は次のとおりです。

  • "サミー "

  • "サメ "

  • "青 "

  • " ocean "

他のデータ型と同様に、マップを変数内に保存し、印刷することができます。

sammy := map[string]string{"name": "Sammy", "animal": "shark", "color": "blue", "location": "ocean"}
fmt.Println(sammy)

これはあなたの出力になります:

Outputmap[animal:shark color:blue location:ocean name:Sammy]

キーと値のペアの順序がずれている可能性があります。 Goでは、マップのデータ型は順不同です。 順序に関係なく、キーと値のペアはそのまま残り、関係の意味に基づいてデータにアクセスできます。

マップアイテムへのアクセス

関連するキーを参照することにより、マップの値を呼び出すことができます。 マップはデータを保存するためのキーと値のペアを提供するため、Goプログラムで重要かつ有用なアイテムになる可能性があります。

Sammyのユーザー名を分離する場合は、 `+ sammy [” name “] +`を呼び出して分離できます。マップと関連キーを保持する変数。 それを印刷してみましょう:

fmt.Println(sammy["name"])

出力として値を受け取ります。

OutputSammy

マップはデータベースのように動作します。スライスの場合のように整数を呼び出して特定のインデックス値を取得する代わりに、キーに値を割り当て、そのキーを呼び出して関連する値を取得します。

キー `” name “`を呼び出すと、そのキーの値、つまり `” Sammy “`を受け取ります。

同様に、同じ形式を使用して、 `+ sammy +`マップの残りの値を呼び出すことができます。

fmt.Println(sammy["animal"])
// returns shark

fmt.Println(sammy["color"])
// returns blue

fmt.Println(sammy["location"])
// returns ocean

マップデータタイプでキーと値のペアを使用することにより、キーを参照して値を取得できます。

キーと値

一部のプログラミング言語とは異なり、Goにはマップのキーまたは値をリストする_convenience_関数がありません。 この例は、辞書用のPythonの `+ .keys()`メソッドです。 ただし、 ` range +`演算子を使用して反復を許可します。

for key, value := range sammy {
   fmt.Printf("%q is the key for the value %q\n", key, value)
}

Goでマップを移動すると、2つの値が返されます。 最初の値がキーになり、2番目の値が値になります。 Goは、これらの変数を正しいデータ型で作成します。 この場合、マップキーは「+ string 」であったため、「 key 」も文字列になります。 ` value +`も文字列です:

Output"animal" is the key for the value "shark"
"color" is the key for the value "blue"
"location" is the key for the value "ocean"
"name" is the key for the value "Sammy"

キーだけのリストを取得するには、範囲演算子を再度使用できます。 キーにアクセスする変数を1つだけ宣言できます。

keys := []string{}

for key := range sammy {
   keys = append(keys, key)
}
fmt.Printf("%q", keys)

プログラムは、キーを格納するスライスを宣言することから始まります。

出力には、マップのキーのみが表示されます。

Output["color" "location" "name" "animal"]

繰り返しますが、キーはソートされていません。 それらをソートする場合は、https://golang.org/pkg/sort [+ sort +]パッケージの `+ sort.Strings +`関数を使用します。

sort.Strings(keys)

この機能を使用すると、次の出力が表示されます。

Output["animal" "color" "location" "name"]

同じパターンを使用して、マップ内の値のみを取得できます。 次の例では、スライスを事前に割り当てて割り当てを回避し、プログラムをより効率的にします。

sammy := map[string]string{"name": "Sammy", "animal": "shark", "color": "blue", "location": "ocean"}

items := make([]string, len(sammy))

var i int

for _, v := range sammy {
   items[i] = v
   i++
}
fmt.Printf("%q", items)

まず、キーを保存するスライスを宣言します。必要なアイテムの数がわかっているため、スライスをまったく同じサイズで定義することで、潜在的なメモリ割り当てを回避できます。 次に、インデックス変数を宣言します。 キーが必要ないため、ループの開始時に「+ _ +」演算子を使用してキーの値を無視します。 出力は次のようになります。

Output["ocean" "Sammy" "shark" "blue"]

マップ内のアイテムの数を決定するには、組み込みの `+ len +`関数を使用できます。

sammy := map[string]string{"name": "Sammy", "animal": "shark", "color": "blue", "location": "ocean"}
fmt.Println(len(sammy))

出力には、マップ内のアイテムの数が表示されます。

Output4

Goにはキーと値を取得するための便利な関数が付属していませんが、必要なときにキーと値を取得するのに数行のコードしか必要ありません。

存在の確認

Goのマップは、要求されたキーが欠落している場合、マップの値タイプのゼロ値を返します。 このため、保存されたゼロと欠落キーを区別する代替方法が必要です。

存在しないことがわかっているマップで値を検索し、返される値を見てみましょう。

counts := map[string]int{}
fmt.Println(counts["sammy"])

次の出力が表示されます。

Output0

キー「+ sammy 」がマップにない場合でも、Goは「+0」の値を返しました。 これは、値のデータ型が `+ int `であり、Goがすべての変数に対してゼロ値を持っているため、 ` 0 +`のゼロ値を返すためです。

多くの場合、これは望ましくなく、プログラムのバグにつながります。 マップで値を検索するとき、Goは2番目の_optional_値を返すことができます。 この2番目の値は「+ bool 」で、キーが見つかった場合は「 true 」、キーが見つからなかった場合は「 false 」になります。 Goでは、これは「 ok 」イディオムと呼ばれます。 2番目の引数をキャプチャする変数に任意の名前を付けることができますが、Goでは常に「 ok +」という名前を付けます。

count, ok := counts["sammy"]

キー「+ sammy」が「+ count +」マップに存在する場合、「 ok」は「+ true 」になります。 そうでなければ、 ` ok +`はfalseになります。

`+ ok +`変数を使用して、プログラムで何をするかを決定できます。

if ok {
   fmt.Printf("Sammy has a count of %d\n", count)
} else {
   fmt.Println("Sammy was not found")
}

これにより、次の出力が得られます。

OutputSammy was not found

Goでは、変数宣言と条件チェックをif / elseブロックと組み合わせることができます。 これにより、このチェックに単一のステートメントを使用できます。

if count, ok := counts["sammy"]; ok {
   fmt.Printf("Sammy has a count of %d\n", count)
} else {
   fmt.Println("Sammy was not found")
}

Goでマップから値を取得するときは、プログラムのバグを回避するために、その存在も確認することを常にお勧めします。

マップの変更

マップは変更可能なデータ構造であるため、変更できます。 このセクションのマップアイテムの追加と削除を見てみましょう。

マップアイテムの追加と変更

メソッドまたは関数を使用せずに、キーと値のペアをマップに追加できます。 これを行うには、マップ変数名を使用し、その後に角括弧で囲まれたキー値「+ [] 」を使用し、等しい値「 = +」を使用して新しい値を設定します。

map[] =

実際には、キーと値のペアを `+ usernames +`というマップに追加することで、この動作を確認できます。

usernames := map[string]string{"Sammy": "sammy-shark", "Jamie": "mantisshrimp54"}

usernames["Drew"] = "squidly"
fmt.Println(usernames)

出力には、マップに新しい `+ Drew:squidly +`キーと値のペアが表示されます。

Outputmap[Drew:squidly Jamie:mantisshrimp54 Sammy:sammy-shark]

マップは順序付けられずに返されるため、このペアはマップ出力のどこでも発生する可能性があります。 後でプログラムファイルで `+ usernames +`マップを使用する場合、追加のキーと値のペアが含まれます。

この構文を使用して、キーに割り当てられた値を変更することもできます。 この場合、既存のキーを参照し、別の値を渡します。

特定のネットワーク上のユーザーのフォロワーを追跡する「+ followers 」というマップを考えてみましょう。 今日のユーザー `” drew “`にはフォロワーが増えたため、 `” drew “`キーに渡された整数値を更新する必要があります。 ` Println()+`関数を使用して、マップが変更されたことを確認します。

followers := map[string]int{"drew": 305, "mary": 428, "cindy": 918}
followers["drew"] = 342
fmt.Println(followers)

出力には、 `+ drew +`の更新された値が表示されます。

Outputmap[cindy:918 drew:342 mary:428]

フォロワーの数が整数値「305」から「342」にジャンプしたことがわかります。

このメソッドを使用して、キーと値のペアをユーザー入力付きのマップに追加できます。 コマンドラインで実行し、ユーザーからの入力により名前と関連ユーザー名を追加できる「+ usernames.go +」という簡単なプログラムを作成しましょう。

usernames.go

package main

import (
   "fmt"
   "strings"
)

func main() {
   usernames := map[string]string{"Sammy": "sammy-shark", "Jamie": "mantisshrimp54"}

   for {
       fmt.Println("Enter a name:")

       var name string
       _, err := fmt.Scanln(&name)

       if err != nil {
           panic(err)
       }

       name = strings.TrimSpace(name)

       if u, ok := usernames[name]; ok {
           fmt.Printf("%q is the username of %q\n", u, name)
           continue
       }

       fmt.Printf("I don't have %v's username, what is it?\n", name)

       var username string
       _, err = fmt.Scanln(&username)

       if err != nil {
           panic(err)
       }

       username = strings.TrimSpace(username)

       usernames[name] = username

       fmt.Println("Data updated.")
   }
}

`+ usernames.go `で、最初に元のマップを定義します。 次に、名前を反復処理するループを設定します。 ユーザーに名前を入力し、それを保存する変数を宣言するように要求します。 次に、エラーが発生したかどうかを確認します。その場合、プログラムは_panic_で終了します。 ` Scanln `は復帰を含む入力全体をキャプチャするため、入力からスペースを削除する必要があります。これを行うには、 ` strings.TrimSpace +`関数を使用します。

`+ if +`ブロックは、名前がマップに存在するかどうかを確認し、フィードバックを出力します。 名前が存在する場合、ループの先頭に戻ります。 名前がマップにない場合は、ユーザーにフィードバックを提供し、関連する名前の新しいユーザー名を要求します。 プログラムは再度エラーがあるかどうかを確認します。 エラーなしで、キャリッジリターンが削除され、ユーザー名の値が名前キーに割り当てられ、データが更新されたというフィードバックが出力されます。

コマンドラインでプログラムを実行しましょう:

go run usernames.go

次の出力が表示されます。

OutputEnter a name:
Sammy
"sammy-shark" is the username of "Sammy"
Enter a name:
Jesse
I don't have Jesse's username, what is it?
JOctopus
Data updated.
Enter a name:

テストが完了したら、 `+ CTRL + C +`を押してプログラムをエスケープします。

これは、マップをインタラクティブに変更する方法を示しています。 この特定のプログラムでは、 `+ CTRL + C +`でプログラムを終了するとすぐに、ファイルの読み書きを処理する方法を実装しない限り、すべてのデータが失われます。

要約すると、 `+ map [key] = value +`構文を使用して、マップにアイテムを追加したり、値を変更したりできます。

マップアイテムの削除

マップデータタイプ内でキーと値のペアを追加して値を変更できるように、マップ内のアイテムを削除することもできます。

マップからキーと値のペアを削除するには、組み込み関数 `+ delete()+`を使用できます。 最初の引数は、削除元のマップです。 2番目の引数は、削除するキーです。

delete(map, key)

許可のマップを定義しましょう:

permissions := map[int]string{1: "read", 2: "write", 4: "delete", 8: "create", 16:"modify"}

「+ modify +」権限は不要になったため、マップから削除します。 次に、地図を印刷して、削除されたことを確認します。

permissions := map[int]string{1: "read", 2: "write", 4: "delete", 8: "create", 16: "modify"}
delete(permissions, 16)
fmt.Println(permissions)

出力は削除を確認します:

Outputmap[1:read 2:write 4:delete 8:create]

行 `+ delete(permissions、16)`は、キーと値のペア `+16:” modify “`を `+ permissions +`マップから削除します。

すべての値のマップをクリアする場合は、同じタイプの空のマップと同じ値に設定することにより、マップをクリアできます。 これにより、使用する新しい空のマップが作成され、古いマップはガベージコレクターによってメモリからクリアされます。

`+ permissions +`マップ内のすべてのアイテムを削除しましょう:

permissions = map[int]string{}
fmt.Println(permissions)

出力は、キーと値のペアがない空のマップがあることを示しています。

Outputmap[]

マップは変更可能なデータ型であるため、追加、変更、およびアイテムの削除とクリアが可能です。

結論

このチュートリアルでは、Goのマップデータ構造について説明しました。 マップはキーと値のペアで構成され、インデックス作成に依存せずにデータを保存する方法を提供します。 これにより、その意味と他のデータ型との関係に基づいて値を取得できます。