23. Maps
Let's navigate!
Map is collection of key value pairs. It goes by various names in other programming languages like dictionaries in Python, objects in JavaScript etc.
Maps are represented as
map[K]V
, where K
and V
are the types of its keys and values.We can declare
map
using var declaration. We are defining string
to be keys for the map and string
to be values. Since map is declared but not initialized with any value, it will be a nil
map. main.go
var capitals map[string]string
fmt.Println(capitals)
fmt.Println("is map nil ==>", capitals == nil)
Maps are created using
make
function call. make
will perform the required memory allocation required to use map. We can add elements to map using map[key] = value
semantics. main.go
caps := make(map[string]string)
// we can also use var keyword as below
// var caps map[string]string = make(map[string]string)
fmt.Println(caps)
fmt.Println("is map nil ==>", caps == nil)
// returns false
caps["India"] = "Delhi"
caps["England"] = "London"
caps["U.S."] = "Washington"
fmt.Println(caps)
We can also use map literal to declare and initialize maps.
make
function call is not required when using map literal.main.go
capitalsOfCountries := map[string]string{
"India": "Delhi",
"England": "London",
"U.S.": "Washington",
}
fmt.Println(capitalsOfCountries)
map elements can be accessed using subscript notion similar to array and slices. In array and slices, index can only be integers. For maps, however, key can be anything which can be compared using
==
comparison.main.go
//accessing map elements
fmt.Println(capitalsOfCountries["India"])
fmt.Println(capitalsOfCountries["England"])
If we try to access map key which does not exists, it will not cause an error, but will return zero value.
main.go
fmt.Println(capitalsOfCountries["XYZ"])
// prints empty string
Zero value for map is nil. Zero value for map element is zero value for type being stored as value.
main.go
var s map[string]string
var i map[string]int
fmt.Println("is s nil =>", s == nil)
fmt.Println("is i nil =>", i == nil)
If map is not nil, but empty, accessing its elements will returns its zero value.
main.go
// zero value for map elements
j := map[string]int{}
fmt.Println(j["India"]) // output : 0
Notice that, event if key does to exist in empty map, it did return zero value.
Similar to slices, maps can be empty or nil. When we use make function call or use map literal for declaring map, it initializes empty map
main.go
var t = make(map[string]string)
k := map[string]int{}
fmt.Println("is t nil =>", t== nil)
fmt.Println("is k nil =>", k== nil)
Both
nil
and empty maps have len()
as zero.main.go
var s map[string]string
var t = make(map[string]string)
fmt.Println(len(s))
fmt.Println(len(t))
Iterating over maps is similar to array and slices, we can use
for...range
loop for iteration. range
works as follows for a mapfor key,value :=range map { // }
main.go
for key, value := range caps {
fmt.Printf("key =>%v, value => %v\n", key, value)
}
Unlike arrays and slices, maps do not guarantee same order. Map is unordered collection of key-value pairs.
If either key or value is not required, we can omit it by using blank identifier.
main.go
for _, value := range caps {
fmt.Printf("value => %v\n", value)
}
for key, _ := range caps {
fmt.Printf("key =>%v\n", key)
}
To find element in map, we provide key to the map to get element/value returned from map. A map does not panic if we try to access key which is not present, instead it returns zero value. To identify if value is returned is actual value present on map or zero value returned due to absence of key, map returns a second value,
ok
which tells if key was found or not. If we see output for below code snippet, when we check for
XYZ
and ABC
, both returns empty string. For XYZ
, value is empty string, while for ABC
, it is missing from map.main.go
cocs := map[string]string{
"India": "Delhi",
"England": "London",
"U.S.": "Washington",
"XYZ": "",
}
fmt.Printf("Checking captial for India-> %v\n",
cocs["India"])
fmt.Printf("Checking captial for XYZ-> %v\n",
cocs["XYZ"])
fmt.Printf("Checking captial for ABC-> %v\n",
cocs["ABC"])
To distinguish between empty/zero value and missing value, we can use
value,ok
semantics.main.go
value, ok := cocs["XYZ"]
if ok {
fmt.Printf("Value is %v \n", value)
} else {
fmt.Println("Key not found")
}
value, ok = cocs["ABC"]
if ok {
fmt.Printf("Value is %v \n", value)
} else {
fmt.Println("Key not found")
}
Updating value is similar to creating a value. We can use
map[key]= value
semantic to update value for given key.main.go
capitals = map[string]string{
"India": "",
"England": "London",
"U.S.": "Washington",
}
capitals["India"] = "Delhi"
fmt.Println(capitals)
Deleting value from map is straightforward. Go provides inbuilt delete function to delete a value from map. Semantics for delete is
delete(mapName,key)
main.go
capitals = map[string]string{
"India": "Pune",
"England": "London",
"U.S.": "Washington",
}
delete(capitals, "England")
fmt.Println(capitals)
Similar to slices, maps can not be compared directly. We can only check if a map is nil or not directly. For other comparisons, we need to write our own for loop for comparison.
GopherCon 2016: Keith Randall - Inside the Map Implementation
Last modified 3yr ago