Go Maps: Difference between revisions
Line 43: | Line 43: | ||
==Testing for a <tt>nil</tt> Map== | ==Testing for a <tt>nil</tt> Map== | ||
<syntaxhighlight lang='go'> | <syntaxhighlight lang='go'> | ||
var mm map[string]int // nil map | |||
var | if mm == nil { | ||
if | |||
// nil map | // nil map | ||
} | } |
Revision as of 22:47, 28 August 2024
External
Internal
Overview
A map is an unordered collection of key/value pairs. The map implementation uses the key as an index and retrieves the associated value in O(1).
The key can be of any type for which the equality operator ==
is defined: integer, floating point and complex number, string, pointer, interface (as long as the dynamic type supports equality), structs and arrays. Slices, functions and struct types that contain slices cannot be used as map keys because equality is not defined on them. An attempt will generate a compiler error. For more details see:
Like slices, maps hold references to the underlying data structures. The map instances must be initialized before attempting to use into them, either by using the make()
function or a composite literal, otherwise you will get a runtime error, because a zero value for a map is nil, which panics when it is written.
The Go documentation used to refer to maps as reference types, but not anymore. The "reference type" terminology was removed from Go documentation.
Maps and Pass-by-Value
Pointers to Maps
nil and Empty Map
nil Map
Declaring a map with the long declaration and without initialization yields a nil
map:
var mm map[string]int
A nil
map is also returned by the new()
function, but new()
returns the pointer to the map, not the map handle itself.
var mmp = new(map[string]int)
An attempt to read a key with the indexing operator []
operator from a nil
map will not panic, but it will return the zero value for the map type.
v, ok := mm["A"] // v is 0 and ok is false
However, an attempt to write a nil
map will panic the program:
m["A"] = 1
will result in:
panic: assignment to entry in nil map
A non-nil
map can be obtained by initializing the map with make()
or with a composite literal.
Testing for a nil Map
var mm map[string]int // nil map
if mm == nil {
// nil map
}
Test nil Map
Empty Map
Declaration and Initialization
A map can be declared with the long variable declaration.
var <mapVarName> map[<keyType>]<valueType>
var mm [string]int
This declaration creates a nil
map. Because nil
maps cannot be written, this form has a limited usefulness.
Inside functions, the short variable declaration can be used with make()
or a composite literal.
Initialization with make()
make()
allocates a the underlying data structures required by the map, and creates a new map header to describe it, all at once. Note that unlike new()
, make()
returns the map, not a pointer. The returned map is empty, but ready to use.
mm := make([string]int)
Initialization with a Composite Literal
Composite literals can be used for map initialization.
Long variable declaration and initialization with type inference:
var mm = map[string]int{"A": 1, "B": 2}
mm := map[string]int{"A": 1, "B": 2}
Operators
Indexing Operator []
Values stored in a map can be referenced with the indexing operator []
, using the [key]
syntax.
The indexing operator returns two values: a copy of the value associated with the key, or the zero-value for the map type if the key does not exist in map, and a boolean that says whether the key exists or not in the map.
The second returned value can be syntactically omitted, but given the fact that the indexing operator returns the zero value for the type and not nil
on missing keys, it is impossible to say without it whether the key is missing, or a zero-value was associated with the key.
mm := map[string]int{"A": 1, "B": 2}
v, ok := mm["A"]
fmt.Printf("%d, %t\n", v, ok) // will display 1, true
Idiom:
if v, ok := mm["A"]; ok {
// use the value
}
If the key does not exist in map, the retuned value is not nil
, but the zero value for the type.
The indexing operator can be used to change the value associated with a key, or to add a new key/value pair:
mm["A"] = 7
mm["C"] = 9
Map Functions
delete()
delete()
is a built-in function that deletes a key/value pair from the map:
mm := map[string]int{"A": 1, "B": 2}
delete(mm, "A")
If the key does not exist in the map, delete()
is a no-op.
len()
len()
is a built-in function that returns the number of keys in the map. Note that the built-in cap()
function does not work on maps. Unlike slices, maps do not have the concept of capacity.
make()
make()
is a built-in function that creates ready-to-use map. See Initialization with make() above.
new()
Iterating over a Map
Use the range
keyword.
for k, v := range mm {
fmt.Printf("%s=%d\n", k, v)
}
If we only want to iterate over keys and the values are not needed, this syntax is valid:
for k := range mm {
fmt.Printf("key: %s\n", k)
}