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条回答
再贱就再见
2楼-- · 2019-01-03 04:16

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]
查看更多
叼着烟拽天下
3楼-- · 2019-01-03 04:21

One line answer:

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

Explanation:

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.

查看更多
我只想做你的唯一
4楼-- · 2019-01-03 04:25

Just use

if len(m) == 0 {
    ...
}
查看更多
男人必须洒脱
5楼-- · 2019-01-03 04:26

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.

查看更多
我想做一个坏孩纸
6楼-- · 2019-01-03 04:27

better way here

if _, ok := dict["foo"]; ok {
    //do something here
}
查看更多
小情绪 Triste *
7楼-- · 2019-01-03 04:32

Short Answer

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

Example

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