カンマokイディオム
0 なのか、無いのか
前のレッスンで、無いキーを読むとゼロ値が返ると書きました。便利ですが、区別が付きません。
Go
counts := map[string]int{"本": 0}
counts["本"] // 0
counts["食品"] // 0本は0件と記録されている。食品はそもそも記録が無い。 どちらも 0 が返るので、この2つを見分けられません。
第4章で「0円の商品」と「見つからない」を区別した話と同じ問題です。
2つ目の戻り値で分かる
マップの読み出しは、2つ受け取れます。
Go
v, ok := counts["食品"]
// v は 0、ok は false2つ目の ok が「キーがあったか」を表します。この書き方を カンマok と呼びます。Go でよく見る言い回しです。
Go
v, ok := counts["本"]
if !ok {
return "記録がありません"
}受け取る数を変えるだけで、返るものが変わります。他ではあまり見ない仕組みですが、マップとチャネル(第7章)と型の変換で共通して使われます。
if の初期化文と組み合わせる
第3章と第4章で出てきた形が、ここでも効きます。
Go
if v, ok := counts["本"]; ok {
return fmt.Sprintf("%d件", v)
}
return "記録がありません"v と ok がこの if の中だけの変数になります。キーがあったときだけ値を使うという意図が、そのまま形になります。
これが Go で最もよく書かれる形の1つです。
いつ使い分けるか
プレーンテキスト
件数を数える counts[key]++ カンマok は要らない
設定値を読む v, ok := m[key] 未設定と 0 を区別したい
存在チェックだけ _, ok := m[key] 値は要らない集計のように「無ければ 0 でよい」場面では、カンマok を使わないほうが短く書けます。区別が要るときだけ使う、という判断になります。
値が要らず存在だけ知りたいときは、_ で捨てます。
Go
if _, ok := counts["本"]; ok {
return "記録があります"
}要件
- カンマok でキーの有無を判定する
- 記録があって在庫が1以上なら
商品名 在庫N点 - 記録があって在庫が0なら
商品名 在庫切れ - 記録が無ければ
商品名 取り扱いなし
入出力例
stockReport("きのこ図鑑") → "きのこ図鑑 在庫3点"
stockReport("中古スマホ") → "中古スマホ 在庫切れ"
stockReport("謎の箱") → "謎の箱 取り扱いなし"
stockReport("古い辞書") → "古い辞書 在庫1点"ヒント
編集 ゆめさく編集部