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{}
The Go Programming Language Specification
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.
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 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
", 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
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
", val, val)
var zeroValue struct{}
if val == zeroValue {
fmt.Println("==", val, ok)
}
}
Playground: https://play.golang.org/p/_XcSCEeEKJV
Output:
struct {} {}
== {} false
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")
}