回答:
一行の答え:
if val, ok := dict["foo"]; ok {
//do something here
}
if
Goのステートメントには、条件と初期化ステートメントの両方を含めることができます。上記の例では両方を使用しています。
2つの変数を初期化します- val
マップから「foo」の値または「ゼロ値」(この場合は空の文字列)のいずれかok
を受け取り、true
「foo」が実際にマップに存在する場合に設定されるブール値を受け取ります
評価するok
だろう、true
「foo」がマップにあった場合
「foo」が実際にマップに存在する場合、if
ステートメントの本体が実行され、val
そのスコープに対してローカルになります。
var val string = ""
は同じままで、val, ok :=
そのブロックでのみ表示される同じ名前の新しいローカル変数を作成します。
if key in dict
です。
Goプログラミング言語仕様に加えて、Effective Goもお読みください。地図のセクションで、彼らはとりわけ、
マップに存在しないキーを使用してマップ値をフェッチしようとすると、マップ内のエントリのタイプのゼロ値が返されます。たとえば、マップに整数が含まれている場合、存在しないキーを検索すると0が返されます。セットは、値タイプboolのマップとして実装できます。マップエントリをtrueに設定して値をセットに入れ、単純なインデックス付けでテストします。
attended := map[string]bool{ "Ann": true, "Joe": true, ... } if attended[person] { // will be false if person is not in the map fmt.Println(person, "was at the meeting") }
欠落しているエントリをゼロ値と区別する必要がある場合があります。「UTC」のエントリはありますか、それともマップにまったくないので0ですか?複数の割り当ての形式で区別できます。
var seconds int var ok bool seconds, ok = timeZone[tz]
明らかな理由により、これは「コンマok」イディオムと呼ばれます。この例では、tzが存在する場合、秒が適切に設定され、okがtrueになります。そうでない場合、秒はゼロに設定され、okはfalseになります。これは、素晴らしいエラーレポートと一緒にまとめる関数です:
func offset(tz string) int { if seconds, ok := timeZone[tz]; ok { return seconds } log.Println("unknown time zone:", tz) return 0 }
実際の値を気にせずにマップ内の存在をテストするには、値の通常の変数の代わりに空白の識別子(_)を使用できます。
_, present := timeZone[tz]
go-nutsメーリングリストを検索したところ、Peter Froehlichによって2009年11月15日に投稿された解決策が見つかりました。
package main
import "fmt"
func main() {
dict := map[string]int {"foo" : 1, "bar" : 2}
value, ok := dict["baz"]
if ok {
fmt.Println("value: ", value)
} else {
fmt.Println("key not found")
}
}
または、よりコンパクトに、
if value, ok := dict["baz"]; ok {
fmt.Println("value: ", value)
} else {
fmt.Println("key not found")
}
この形式のif
ステートメントを使用するvalue
と、and ok
変数はif
条件内でのみ表示されます。
_, ok := dict["baz"]; ok
。_
一部には、一時変数を作成するのではなく、離れた値をスローします。
_, exists := timeZone[tz] // Just checks for key existence
val, exists := timeZone[tz] // Checks for key existence and retrieves the value
ここだゴー遊び場の例が。
マップに存在しないキーを使用してマップ値をフェッチしようとすると、マップ内のエントリのタイプのゼロ値が返されます。たとえば、マップに整数が含まれている場合、存在しないキーを検索すると0が返されます。
欠落しているエントリをゼロ値と区別する必要がある場合があります。「UTC」のエントリはありますか、それともマップにまったくないので空の文字列ですか?複数の割り当ての形式で区別できます。
var seconds int var ok bool seconds, ok = timeZone[tz]
明らかな理由により、これは「コンマok」イディオムと呼ばれます。この例では、tzが存在する場合、秒が適切に設定され、okがtrueになります。そうでない場合、秒はゼロに設定され、okはfalseになります。これは、素晴らしいエラーレポートと一緒にまとめる関数です:
func offset(tz string) int { if seconds, ok := timeZone[tz]; ok { return seconds } log.Println("unknown time zone:", tz) return 0 }
実際の値を気にせずにマップ内の存在をテストするには、値の通常の変数の代わりに空白の識別子(_)を使用できます。
_, present := timeZone[tz]
他の回答で指摘されているように、一般的な解決策は、特殊な形式の割り当てでインデックス式を使用することです。
v, ok = a[x]
v, ok := a[x]
var v, ok = a[x]
var v, ok T = a[x]
これは素晴らしく、きれいです。ただし、いくつかの制限があります。特殊な形式の割り当てである必要があります。右側の式はマップインデックス式のみである必要があり、左側の式リストには、2つのオペランドが含まれている必要がありますbool
。この特別なフォームの結果の最初の値はキーに関連付けられた値になり、2番目の値は指定されたキーを持つマップにエントリが実際にあるかどうかを示します(キーがマップに存在する場合)。結果の1つが不要な場合は、左側の式リストに空白の識別子が含まれる場合もあります。
インデックス付きのマップ値にnil
キーが含まれているか含まれていない場合、インデックス式はマップの値タイプのゼロ値に評価されることを知っておくことが重要です。だから例えば:
m := map[int]string{}
s := m[1] // s will be the empty string ""
var m2 map[int]float64 // m2 is nil!
f := m2[2] // f will be 0.0
fmt.Printf("%q %f", s, f) // Prints: "" 0.000000
Go Playgroundでお試しください。
したがって、マップでゼロ値を使用しないことがわかっている場合は、これを利用できます。
たとえば、値のタイプがstring
であり、値が空の文字列(string
タイプのゼロ値)であるマップにエントリを格納しないことがわかっている場合は、特殊でないキーを比較して、キーがマップにあるかどうかをテストすることもできます。ゼロ値への(の結果)インデックス式の形式:
m := map[int]string{
0: "zero",
1: "one",
}
fmt.Printf("Key 0 exists: %t\nKey 1 exists: %t\nKey 2 exists: %t",
m[0] != "", m[1] != "", m[2] != "")
出力(Go Playgroundで試してください):
Key 0 exists: true
Key 1 exists: true
Key 2 exists: false
実際には、ゼロ値をマップに格納しない場合が多いため、これはかなり頻繁に使用できます。たとえば、インターフェースと関数タイプにはゼロ値nil
がありますが、これはマップに保存されないことがよくあります。したがって、キーがマップにあるかどうかのテストは、それをと比較することで実現できますnil
。
この「テクニック」の使用には、別の利点もあります。コンパクトな方法で複数のキーの存在を確認できる(特別な「コンマok」フォームでは確認できません)。詳細:キーが複数のマップに1つの条件で存在するかどうかを確認する
存在しないキーでインデックスを作成するときに値タイプのゼロ値を取得すると、値を持つマップをセットbool
として便利に使用することもできます。例えば:
set := map[string]bool{
"one": true,
"two": true,
}
fmt.Println("Contains 'one':", set["one"])
if set["two"] {
fmt.Println("'two' is in the set")
}
if !set["three"] {
fmt.Println("'three' is not in the set")
}
出力します(Go Playgroundで試してください):
Contains 'one': true
'two' is in the set
'three' is not in the set
関連項目を参照:一意の文字列を含む配列を作成するにはどうすればよいですか?
T
入っvar v, ok T = a[x]
てるの?されていないok
ブール値でなければなりませんか?
var empty struct{}
var ok bool
var m map[string]struct{}
m = make(map[string]struct{})
m["somestring"] = empty
_, ok = m["somestring"]
fmt.Println("somestring exists?", ok)
_, ok = m["not"]
fmt.Println("not exists?", ok)
次に、maps.goを実行します。本当は存在しませんか?偽
_, ok = m["somestring"]
する必要があります=_, ok := m["somestring"]
これは、下記載され、「インデックス式」。
特殊なフォームの割り当てまたは初期化で使用されるmap [K] Vタイプのマップのインデックス式
v, ok = a[x] v, ok := a[x] var v, ok = a[x]
追加の型なしブール値を生成します。okの値は、キーxがマップに存在する場合はtrue、それ以外の場合はfalseです。
この目的で、2つの値の割り当てを使用できます。以下のサンプルプログラムを確認してください
package main
import (
"fmt"
)
func main() {
//creating a map with 3 key-value pairs
sampleMap := map[string]int{"key1": 100, "key2": 500, "key3": 999}
//A two value assignment can be used to check existence of a key.
value, isKeyPresent := sampleMap["key2"]
//isKeyPresent will be true if key present in sampleMap
if isKeyPresent {
//key exist
fmt.Println("key present, value = ", value)
} else {
//key does not exist
fmt.Println("key does not exist")
}
}