0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

GoのMapで未割り当てのキーの値はゼロ値

Posted at

ドキュメントに書かれているけど、今まで知らなかった...という話です。

Mapから値を取り出す前にv, ok := m[key]; okでチェックする

書いてるとおりですが、いつも、次のようなコードを書いていました。

type Hoge {
  HasX bool
}

という型があったとして、m map[string]Hogeに値が割り当てられており、かつ、hasXtrueかどうかをチェックする関数があったとすると、以下のように書いていました。

func checkHasX(m map[string]Hoge, k string) bool {
	if v, ok := m[k]; ok {
		return false
	}
	return v.HasX
}

別にこのように書いても間違いではないとは思いますが、Goのドキュメントには以下のように書いています。

For a of map type M:
x's type must be assignable to the key type of M
if the map contains an entry with key x, a[x] is the map element with key x and the type of a[x] is the element type of M
if the map is nil or does not contain such an entry, a[x] is the zero value for the element type of M

最後の文ですね。if the map is nil or does not contain such an entry, a[x] is the zero value for the element type of Mとあるので、Mのゼロ値となるとあります。

Mapがnilまたは、キーに値が未割り当てだった場合はゼロ値が返る

つまり、以下のように書いても同じということです。

func checkKey(m map[string]Hoge, k string) bool {
	return m[k].hasX
}

ですので、以下のようなコードも、コメントに書いている通りの結果になります。

	m := map[string]bool{}
	fmt.Printf("%v", m["hoge"]) // false
	m := map[string]string{}
	fmt.Printf("%v", m["hoge"]) // 空文字
	var m map[string]int // Map自体がnilの場合でも同じ
	fmt.Printf("%v", m["hoge"]) // 0

なお、当然ですが、ゼロ値が帰ってくるからと言って、アサインされているわけではないです。

	var m map[string]int
	fmt.Printf("%v", m["hoge"]) // 0
    _, ok := m["hoge"]
	fmt.Printf("%v", ok) // false

つまり、v, ok := m[key]; ok は場合によっては不要

もちろん、書いているコードによっては、未割り当てかどうかを確認する必要がある場合もあるとは思いますが、値が入ってなくても、入っていても、ゼロ値がfalse扱いというようなケースに関しては、特に割当てられているかをチェックする必要はないです。

終わり

ドキュメントに書いてあるのに、今まで気づいてなかったという話でした。ちなみに、Effective Goにもちゃんと書いてあります

An attempt to fetch a map value with a key that is not present in the map will return the zero value for the type of the entries in the map. For instance, if the map contains integers, looking up a non-existent key will return 0. A set can be implemented as a map with value type bool. Set the map entry to true to put the value in the set, and then test it by simple indexing.

むしろ、存在チェックがその後に書かれているくらいなので、至って常識的な話だったのかもしれません。

ゼロ値がfalseって、なんとなくPerlっぽいなぁ、と思ったりしました。

存在しないキーにアクセスしただけでエラーになる言語もあるので、意外に思ったのですが、こうしとかないと、ちゃんとチェックしていないコードの場合、実行時にpanicしまくるからかなぁ?などと思ったりしました。

というわけdドキュメントはちゃんと読みましょう、と改めて思いました。反省。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?