Use an “index expression“. Buried in that official doc link is an example like this:
value, ok := someMap["someKey"]
if ok {
fmt.Println("it exists!")
doThings(value)
} else {
fmt.Println("it does not exist")
}
In other languages, using index expressions (a term I just learned) could be risky if the key doesn’t exist:
# python raises an exception
obj["bad_key"] -> KeyError: 'bad_key'
# ruby returns nil
obj["bad_key"] -> nil
// javascript returns undefined
obj.badKey -> undefined
Instead of blowing up, or returning a generic (and possibly dangerous) value, Go gives back a second piece of information letting you know if the key you used was ok or not. I suspect this is due to how Golang uses zero values. I’ll explain with an example:
myMap := map[string]int{
"a": 1,
"b": 2,
}
// now let's try and access a key that doesn't exist
myMap["fakeKey"]
// 0
“Why would an invalid key return a value of 0
?” you might be asking. Good question. That’s because 0
is the zero value of any integer type in Golang. Since this map is mapping string
keys to integer
values, when a non-existent key is passed the map returns the zero value of the map’s value type, which in this case is 0
.
Let’s do one more example:
anotherMap := map[string]bool {
"a": true,
"b": false,
}
anotherMap["c"]
// false
This second example is mapping strings to boolean values, and the zero value for booleans in Golang is false
.
Without checking if your map key was actually found, you could cause a hard-to-diagnose bug; zero values look like valid values because they are! To avoid those bugs, use the ok
value returned from the index expression:
value, ok := anotherMap["c"]
if !ok {
// log a message, maybe raise an error
} else {
// all good, do what you came to do
}
Helpful Links
- Index expressions – golang docs
- Zero values – golang docs