By grokus

2010-01-12 16:18:20 8 Comments

I know I can iterate over a map m by,

for k, v := range m { ... }

and look for a key but is there a more efficient way of testing a key's existence in a map?

I couldn't find the answer in the language spec.


@Fathah Rehman P 2018-09-21 10:27:31

A two value assignment can be used for this purpose. Please check my sample program below

package main

import (

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")

@mroman 2018-06-13 18:54:48

It is mentioned under "Index expressions".

An index expression on a map a of type map[K]V used in an assignment or initialization of the special form

v, ok = a[x] 
v, ok := a[x] 
var v, ok = a[x]

yields an additional untyped boolean value. The value of ok is true if the key x is present in the map, and false otherwise.

@Amazingandyyy 2017-10-18 05:17:21

better way here

if _, ok := dict["foo"]; ok {
    //do something here

@icza 2017-04-07 08:05:59

As noted by other answers, the general solution is to use an index expression in an assignment of the special form:

v, ok = a[x]
v, ok := a[x]
var v, ok = a[x]
var v, ok T = a[x]

This is nice and clean. It has some restrictions though: it must be an assignment of special form. Right-hand side expression must be the map index expression only, and the left-hand expression list must contain exactly 2 operands, first to which the value type is assignable, and a second to which a bool value is assignable. The first value of the result of this special form index expression will be the value associated with the key, and the second value will tell if there is actually an entry in the map with the given key (if the key exists in the map). The left-hand side expression list may also contain the blank identifier if one of the results is not needed.

It's important to know that if the indexed map value is nil or does not contain the key, the index expression evaluates to the zero value of the value type of the map. So for example:

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

Try it on the Go Playground.

So if we know that we don't use the zero value in our map, we can take advantage of this.

For example if the value type is string, and we know we never store entries in the map where the value is the empty string (zero value for the string type), we can also test if the key is in the map by comparing the non-special form of the (result of the) index expression to the zero value:

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] != "")

Output (try it on the Go Playground):

Key 0 exists: true
Key 1 exists: true
Key 2 exists: false

In practice there are many cases when we don't store the zero-value value in the map, so this can be used quite often. For example interfaces and function types have a zero value nil, which we often don't store in maps. So testing if a key is in the map can be achieved by comparing it to nil.

Using this "technique" has another advantage too: you can check existence of multiple keys in a compact way (you can't do that with the special "comma ok" form). More about this: Check if key exists in multiple maps in one condition

@Kokizzu 2017-05-12 04:31:43

what is T in var v, ok T = a[x]? isn't ok must be bool?

@icza 2017-05-12 07:53:50

@Kokizzu That's the general form of the variable declaration. At first we might think it would only work (compile) if the map would be of type map[bool]bool and T is bool, but it also works if map is of type map[interface{}]bool and T is interface{}; moreover it also works with custom types having bool as underlying type, see all on the Go Playground. So since that form is valid with multiple types substituted for T, that's why the general T is used. Type of ok can be anything to which an untyped bool can be assigned.

@peterSO 2010-01-12 17:37:55

Edit: The following answer is prior to Go 1. Starting with Go 1, it is no longer accurate / valid.

In addition to The Go Programming Language Specification, you should read Effective Go. In the section on maps, they say, amongst other things:

"An attempt to fetch a map value with a key that is not present in the map will cause the program to crash, but there is a way to do so safely using a multiple assignment."

var seconds int
var ok bool
seconds, ok = timeZone[tz]

"To test for presence in the map without worrying about the actual value, you can use the blank identifier, a simple underscore (_). The blank identifier can be assigned or declared with any value of any type, with the value discarded harmlessly. For testing presence in a map, use the blank identifier in place of the usual variable for the value."

_, present := timeZone[tz]

@Adam Crossland 2011-07-30 15:30:09

This answer is much better and complete than the one that was accepted.

@Andrea Spadaccini 2012-01-13 23:35:11

Please note that this is not valid anymore, as the spec now says "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.". So it will not segfault anymore (and this cost me many bits of mental sanity tonight). So, use the accepted answer.

@jameshfisher 2015-06-10 14:34:20

@AndreaSpadaccini Ugh, why on earth did they make that change? They had the right behavior in the first place. Anyway, thanks for correcting this.

@Dave C 2015-06-17 14:43:08

@peterSO, if you're going to rollback the edit (which was probably too large an edit) then please provide your own edit that either outright replaces this pre-Go1 spec quote or otherwise clarifies that Go1 doesn't crash. IMO it shouldn't be required for people to read all the comments or follow the link to notice part of this answer is out of date.

@Hephaestus 2016-07-07 15:55:52

Agree with @jameshfisher. This newer behavior is something I'd expect from PHP, but not from Go.

@Matthew Rankin 2015-11-09 21:38:00

Short Answer

_, exists := timeZone[tz]    // Just checks for key existence
val, exists := timeZone[tz]  // Checks for key existence and retrieves the value


Here's an example at the Go Playground.

Longer Answer

Per the Maps section of 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.

Sometimes you need to distinguish a missing entry from a zero value. Is there an entry for "UTC" or is that the empty string because it's not in the map at all? You can discriminate with a form of multiple assignment.

var seconds int
var ok bool
seconds, ok = timeZone[tz]

For obvious reasons this is called the “comma ok” idiom. In this example, if tz is present, seconds will be set appropriately and ok will be true; if not, seconds will be set to zero and ok will be false. Here's a function that puts it together with a nice error report:

func offset(tz string) int {
    if seconds, ok := timeZone[tz]; ok {
        return seconds
    log.Println("unknown time zone:", tz)
    return 0

To test for presence in the map without worrying about the actual value, you can use the blank identifier (_) in place of the usual variable for the value.

_, present := timeZone[tz]

@hacky 2015-09-02 04:39:36

Just use

if len(m) == 0 {

@Dave C 2015-09-02 17:52:03

That tells you if the whole map is empty which is not what this questions is asking about. It's asking to test if a specific key is present or not.

@wandermonk 2017-10-21 01:59:51

Please try to provide more explanation why do you think this is the best way to do.

@Aditya Satyavada 2019-01-24 07:36:25

This only tells us the map is empty.

@Lady_Exotel 2015-07-22 12:19:35

    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)

Then, go run maps.go somestring exists? true not exists? false

@Lady_Exotel 2015-07-22 12:20:15

Gets rid of the need for int

@tomasz 2015-07-22 15:15:54

Thanks for the contribution, but I think the current answers cover the question well. From what you're saying here your answer would more fit a Best way of implementing set in Go type of question.

@marketer 2010-01-12 16:48:48

One line answer:

if val, ok := dict["foo"]; ok {
    //do something here


if statements in Go can include both a condition and an initialization statement. The example above uses both:

  • initializes two variables - val will receive either the value of "foo" from the map or a "zero value" (in this case the empty string) and ok will receive a bool that will be set to true if "foo" was actually present in the map

  • evaluates ok, which will be true if "foo" was in the map

If "foo" is indeed present in the map, the body of the if statement will be executed and val will be local to that scope.

@Chmouel Boudjnah 2014-04-29 06:39:20

This may can be better explained how it works (like the other comment from peterSO)

@Kiril 2014-05-07 15:49:51

What would happen if one line above if val,ok ... a val was declared: var val string = ""?

@OneOfOne 2014-05-20 01:22:10

@Kiril var val string = "" will remain the same, val, ok := creates a new local variable with the same name that's only visibile in that block.

@Mheni 2018-06-17 22:16:57

great answer, would you say the complexity of this is O(1) ??

@3ocene 2018-10-09 20:50:32

@Mheni, I know I'm a bit late here, but this question discusses the lookup complexity in go. Most of the time the amortized complexity is O(1) but it's worth reading the answers on that question.

@Pranjal Mittal 2018-12-08 23:58:16

Such a confusing syntax compared to python's if key in dict.

@grokus 2010-01-12 16:40:52

Searched on the go-nuts email list and found a solution posted by Peter Froehlich on 11/15/2009.

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")

Or, more compactly,

if value, ok := dict["baz"]; ok {
    fmt.Println("value: ", value)
} else {
    fmt.Println("key not found")

Note, using this form of the if statement, the value and ok variables are only visible inside the if conditions.

@Matthew Crumley 2010-01-12 17:03:17

If you really are just interested in whether the key exists or not, and don't care about the value, you can use _, ok := dict["baz"]; ok. The _ part throws the value away instead of creating a temporary variable.

Related Questions

Sponsored Content

8 Answered Questions

[SOLVED] How to remove a key from a Python dictionary?

21 Answered Questions

[SOLVED] Check if a given key already exists in a dictionary

  • 2009-10-21 19:05:09
  • Mohan Gulati
  • 2794400 View
  • 2642 Score
  • 21 Answer
  • Tags:   python dictionary

44 Answered Questions

[SOLVED] How to merge two dictionaries in a single expression?

15 Answered Questions

[SOLVED] Add new keys to a dictionary?

  • 2009-06-21 22:07:39
  • lfaraone
  • 2889373 View
  • 2219 Score
  • 15 Answer
  • Tags:   python dictionary

42 Answered Questions

[SOLVED] How do I sort a dictionary by value?

38 Answered Questions

[SOLVED] How do I efficiently iterate over each entry in a Java Map?

5 Answered Questions

[SOLVED] Getting a slice of keys from a map

  • 2014-01-26 11:48:24
  • Saswat Padhi
  • 138910 View
  • 161 Score
  • 5 Answer
  • Tags:   go

49 Answered Questions

[SOLVED] Sort a Map<Key, Value> by values

3 Answered Questions

[SOLVED] Iterating over all the keys of a map

  • 2009-12-03 17:15:18
  • Martin Redmond
  • 183845 View
  • 252 Score
  • 3 Answer
  • Tags:   loops dictionary go

8 Answered Questions

[SOLVED] Java Class that implements Map and keeps insertion order?

Sponsored Content