Go Maps Made Simple
In Go, maps are used to store data in key-value pairs. That means each
piece of data has a unique key that points to a value.
What You Need to Know About Maps:
- A map holds key:value pairs. For example:{"name": "Alice", "age": 25}
- Here, "name" and "age" are keys, and "Alice" and 25 are their values.
- Maps are unordered, which means the data inside doesn’t follow a fixed order.
- You can change a map by adding, updating, or deleting items.
- Duplicate keys are not allowed. If you add the same key again, the old value will be replaced.
- You can find out how many items are in a map using the len() function.
- If a map hasn’t been created yet, its default value is nil. A nil map doesn’t work until you initialize it.
- Maps in Go use an underlying hash table to store data efficiently.
- There are different ways to create maps in Go, such as using a map literal or the make() function.
Example:
// Creating a map with some values
person := map[string]string{
"name": "John",
"city": "New York",
}
// Getting the number of items in the map
fmt.Println(len(person))
// Output: 2
Creating Maps in Go Using var and :=
In Go, you can create maps in two main ways:
1. Using var
You can declare a map with the var keyword and assign key-value
pairs.
var a = map[KeyType]ValueType{
key1: value1,
key2: value2,
}
2. Using := (Short Variable Declaration)
This is a shorter way to create and assign a map at the same time.
b := map[KeyType]ValueType{
key1: value1,
key2: value2,
}
Example: Creating Maps
Here's a full Go program that creates two maps — one using var, the other
using :=:
package main
import "fmt"
func main() {
var a = map[string]string{
"brand": "Ford",
"model": "Mustang",
"year": "1964",
}
b := map[string]int{
"Oslo": 1,
"Bergen": 2,
"Trondheim": 3,
"Stavanger": 4,
}
fmt.Printf("a\t%v\n",
a)
fmt.Printf("b\t%v\n",
b)
}
Output:
a map[brand:Ford model:Mustang year:1964]
b map[Bergen:2 Oslo:1 Stavanger:4 Trondheim:3]
Creating Maps With make()
The built‑in make function allocates and returns an empty map that you
can populate later.
// Long form
var m = make(map[KeyType]ValueType)
// Short form (idiomatic in Go)
n := make(map[KeyType]ValueType)
Example:
Below, we build two maps at runtime—one that holds car details and
another that assigns IDs to Norwegian cities.
package main
import "fmt"
func main() {
// Map for car information
cars := make(map[string]string)
cars["brand"] = "Ford"
cars["model"] = "Mustang"
cars["year"] = "1964"
// Map for city IDs
cities := make(map[string]int)
cities["Oslo"] = 1
cities["Bergen"] = 2
cities["Trondheim"] = 3
cities["Stavanger"] = 4
fmt.Printf("cars:\t%v\n",
cars)
fmt.Printf("cities:\t%v\n", cities)
}
Output:
cars: map[brand:Ford model:Mustang year:1964]
cities: map[Bergen:2 Oslo:1 Stavanger:4 Trondheim:3]
Declaring an Empty Map in Go
You have two ways to end up with an “empty” map:
Rule of thumb: Use make unless you truly want a nil map for some
special purpose (e.g., to signal “no data”).
Example:
package main
import "fmt"
func main() {
a := make(map[string]string)
// empty but non‑nil
var b map[string]string
// nil map
fmt.Println(a ==
nil) // false — ready to use
fmt.Println(b ==
nil)
// true — nil, will panic if written to
}
Output:
false
true
Because a was created with make, it’s a valid map and can be populated
right away. b, on the other hand, is nil; writing to it (b["key"] =
"value") would trigger a panic at runtime.
Allowed Key Types in Maps
In Go, map keys must be of a type that supports the equality operator
(==). Valid key types include:
- Booleans
- Numbers
- Strings
- Arrays
- Pointers
- Structs
- Interfaces (only if the underlying dynamic type supports equality)
Invalid Key Types
The following types cannot be used as map keys because they do not
support the equality operator:
- Slices
- Maps
- Functions
Permissible Value Types
A map’s values can be any Go type—primitive or user‑defined.
Reading Data from a Map
To look up a value, put the desired key in square brackets after the
map variable:
value := myMap[key]
Example:
package main
import "fmt"
func main() {
car := make(map[string]string)
// create an empty map
// populate the map
car["brand"] = "Ford"
car["model"] = "Mustang"
car["year"] = "1964"
// retrieve and print a value
fmt.Println(car["brand"])
// Output: Ford
}
Output:
Ford
Adding or Updating Entries in a Map
You insert a new key–value pair, or change an existing one, with the
assignment syntax:
mapVar[key] = value
Example:
package main
import "fmt"
func main() {
car := make(map[string]string)
// create an empty map
// initial data
car["brand"] = "Ford"
car["model"] = "Mustang"
car["year"] = "1964"
fmt.Println(car)
// map[brand:Ford model:Mustang year:1964]
// modify an existing entry
car["year"] = "1970"
// add a brand‑new entry
car["color"] = "red"
fmt.Println(car)
// map[brand:Ford color:red model:Mustang year:1970]
}
The first fmt.Println shows the map’s original state, while the second
confirms that year was updated and color was added.
Removing Elements from a Map
To remove an element from a map, use the built-in delete()
function:
delete(mapVar, key)
Example:
package main
import "fmt"
func main() {
car := make(map[string]string)
car["brand"] = "Ford"
car["model"] = "Mustang"
car["year"] = "1964"
fmt.Println(car)
// map[brand:Ford model:Mustang year:1964]
delete(car, "year")
// remove the "year" key
fmt.Println(car)
// map[brand:Ford model:Mustang]
}
Checking If a Key Exists in a Map
- To determine whether a key exists in a map, use this syntax:
- value, exists := mapVar[key]
- If you only care about whether the key exists (not the value), use the blank identifier _:
- _, exists := mapVar[key]
Example:
package main
import "fmt"
func main() {
car := map[string]string{
"brand": "Ford",
"model": "Mustang",
"year": "1964",
"day": "",
}
val1, ok1 := car["brand"]
// key exists, value is "Ford"
val2, ok2 := car["color"]
// key does not exist
val3, ok3 := car["day"]
// key exists, value is an empty string
_, ok4 := car["model"]
// check existence only
fmt.Println(val1, ok1)
// Ford true
fmt.Println(val2, ok2)
// false
fmt.Println(val3,
ok3)
// true
fmt.Println(ok4)
// true
}
This output confirms:
- "brand" exists and has a value
- "color" does not exist
- "day" exists but has an empty string as its value
- "model" exists (checked without retrieving the value)
Maps Are Reference Types
A map variable holds a reference to an underlying hash table.
If two map variables point to the same table, modifying either one
changes the shared data:
package main
import "fmt"
func main() {
car := map[string]string{
"brand": "Ford",
"model": "Mustang",
"year": "1964",
}
copyRef := car
// copyRef and car reference the same map
fmt.Println(car)
// map[brand:Ford model:Mustang year:1964]
fmt.Println(copyRef)
// map[brand:Ford model:Mustang year:1964]
copyRef["year"] = "1970"
// update through copyRef
fmt.Println("After
change:")
fmt.Println(car)
// map[brand:Ford model:Mustang year:1970]
fmt.Println(copyRef)
// map[brand:Ford model:Mustang year:1970]
}
Iterating Over a Map
Use range to loop through key–value pairs. Remember that the
iteration order is not guaranteed:
package main
import "fmt"
func main() {
nums := map[string]int{
"one": 1,
"two": 2,
"three": 3,
"four": 4,
}
for k, v := range nums {
fmt.Printf("%s : %d, ", k, v)
}
// Example output (order will vary):
// two : 2, three : 3, four : 4, one : 1,
}
Iterating Over a Map in a Defined Order
Because Go maps are inherently unordered, you must keep a separate
slice that lists the keys in the order you want. Then iterate over
that slice to access the map’s values in sequence.
package main
import "fmt"
func main() {
// the map itself (unordered)
numbers := map[string]int{
"one": 1,
"two": 2,
"three": 3,
"four": 4,
}
// desired iteration order
order := []string{"one", "two", "three",
"four"}
//– Unordered iteration (order will vary each run)
for k, v := range numbers {
fmt.Printf("%s : %d, ", k, v)
}
fmt.Println()
//– Ordered iteration using the key slice
for _, key := range order {
fmt.Printf("%s : %d, ", key, numbers[key])
}
}
Typical output:
two : 2, three : 3, four : 4, one : 1,
one : 1, two : 2, three : 3, four : 4,
The first loop reflects the map’s unpredictable ordering, while the
second loop follows the explicit sequence defined in order.
More topic in Go