How to check if a map contains a key in go?

2019-01-03 04:06发布

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.

标签: dictionary go
10条回答
Anthone
2楼-- · 2019-01-03 04:36

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.

查看更多
一纸荒年 Trace。
3楼-- · 2019-01-03 04:37

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

查看更多
女痞
4楼-- · 2019-01-03 04:39
    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

查看更多
别忘想泡老子
5楼-- · 2019-01-03 04:41

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

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")
    }
}
查看更多
登录 后发表回答