4

Ok so according to this:

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

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

that's fine, but how come we can't do this:

val, ok := m["foo"]

if val == nil {   // cannot compare val to nil

}

I get a compilation error saying I can't compare val to nil, but then what value does val have? What can I compare it to, to determine if it exists or not?

the type of m is like:

type m map[string]struct{}

2 Answers2

2

The Go Programming Language Specification

Index expressions

For a of map type M: if the map is nil or does not contain such an entry, a[x] is the zero value for the element type of M.

The zero value

When storage is allocated for a variable, either through a declaration or a call of new, or when a new value is created, either through a composite literal or a call of make, and no explicit initialization is provided, the variable or value is given a default value. Each element of such a variable or value is set to the zero value for its type: false for booleans, 0 for numeric types, "" for strings, and nil for pointers, functions, interfaces, slices, channels, and maps.


The Go Programming Language Specification

Composite literals

Composite literals construct values for structs, arrays, slices, and maps and create a new value each time they are evaluated. They consist of the type of the literal followed by a brace-bound list of elements. Each element may optionally be preceded by a corresponding key. For struct literals the following rules apply:

A literal may omit the element list; such a literal evaluates to the zero value for its type.

For your example, type struct{}, omit the element list from the composite literal, struct{}{}, for the zero value.

For example,

package main

import "fmt"

func main() {
    m := map[string]struct{}{}
    val, ok := m["foo"]
    fmt.Printf("%T %v\n", val, val)
    if val == struct{}{} {
        fmt.Println("==", val, ok)
    }
}

Playground: https://play.golang.org/p/44D_ZfFDA77

Output:

struct {} {}
== {} false

The Go Programming Language Specification

Variable declarations

A variable declaration creates one or more variables, binds corresponding identifiers to them, and gives each a type and an initial value.

If a list of expressions is given, the variables are initialized with the expressions following the rules for assignments. Otherwise, each variable is initialized to its zero value.

If a type is present, each variable is given that type. Otherwise, each variable is given the type of the corresponding initialization value in the assignment.

In your example, you could declare a variable of type struct{} with no initial value, which would be initialized to the zero value for the struct{} type.

For example,

package main

import "fmt"

func main() {
    m := map[string]struct{}{}
    val, ok := m["foo"]
    fmt.Printf("%T %v\n", val, val)
    var zeroValue struct{}
    if val == zeroValue {
        fmt.Println("==", val, ok)
    }
}

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

Output:

struct {} {}
== {} false
peterSO
  • 158,998
  • 31
  • 281
  • 276
  • according to this, the zero-value of a struct should be nil? https://stackoverflow.com/questions/28625794/structs-zero-value-in-golang –  Oct 27 '18 at 19:40
  • 1
    @MrCholo: The zero value of a `struct` is the composite of the zero values of its fields. – peterSO Oct 27 '18 at 19:41
  • Ah shizz, that doesn't sound like `nil` to me, hence why I was getting what I was getting in the OP –  Oct 27 '18 at 19:55
  • I wonder what the point of `composite of the zero values of its fields` is, why not just nil? Because NPEs are bad? –  Oct 27 '18 at 19:55
-1

You can most certainly do what you did above. Comparing to nil depends on the type of value you have in map. If its interface{} you can compare it to nil:

m := map[string]interface{}{}

val, _ := m["foo"]

if val == nil {
    fmt.Println("no index")
}
xReprisal
  • 810
  • 8
  • 23