当键不在地图中时不引发错误(例如Python)的好处是什么? [关闭]

In Go, let m is map object that map string to int, suppose "foo" is not a key of m, then the statement

m["foo"]

returns two value 0 and false which false implies "foo" is not a key of m. Could you give some situations, examples that the go's property is useful?

Go does not raise errors. Go reports errors.


A common use of a map element zero value:

package main

import (
    "fmt"
)

func main() {
    counts := map[string]int{}
    fmt.Println(counts)

    // Equivalent:
    // counts["foo"] = counts["foo"] + 1
    // counts["foo"] += 1
    // counts["foo"]++

    counts["foo"]++
    fmt.Println(counts)

    counts["foo"]++
    fmt.Println(counts)
}

Playground: https://play.golang.org/p/nvHBrgV_lFU

Output:

map[]
map[foo:1]
map[foo:2]

A common use of the comma, ok form map index expression:

package main

import (
    "fmt"
)

func main() {
    m := map[string]map[string]int{}
    fmt.Println(m)

    // panic: assignment to entry in nil map
    // m["K1"]["K2"]++

    _, ok := m["K1"]
    if !ok {
        m["K1"] = map[string]int{}
    }
    m["K1"]["K2"]++
    fmt.Println(m)

    m["K1"]["K2"]++
    fmt.Println(m)
}

Playground: https://play.golang.org/p/9byxSSIWBre

Output:

map[]
map[K1:map[K2:1]]
map[K1:map[K2:2]]

There was a time before Go 1 when indexing a map with a non-existing key crashed the app. This was changed to return the zero value of the value type of the map. This was a design decision which allows the (limited) use of uninitialized language constructs to be used without extra checks, which simplifies code.

For example you can for range over nil slices and nil maps, you can check their length etc. The result is the same of course: iterating over a nil slice or map will result in zero iterations, and the length of nil slices and maps is 0, but you do not need to use an if statement beforehand to tell if the value is non-nil (in order to tell if you can range over them or index them).

PeterSO already showed a good example when the zero value for non-existing keys is useful: counters.

Another famous example is a map being used as a set. If you choose the value type to be bool, you don't have to initialize values that are not in the set. Indexing the map tells if a value (the key) is in the set, and if it's not, the zero value of bool type being false will tell you that it's not in the set.

For example:

fruits := map[string]bool{}

// Add elements to the set:
fruits["apple"] = true
fruits["banana"] = true

// Test if elements are in the map:
fmt.Println("Is apple in the set?", fruits["apple"])
fmt.Println("Is banana in the set?", fruits["banana"])
fmt.Println("Is plum in the set?", fruits["plum"])
fmt.Println("Is lemon in the set?", fruits["lemon"])

Output (try it on the Go Playground):

Is apple in the set? true
Is banana in the set? true
Is plum in the set? false
Is lemon in the set? false