mdawar.dev

A blog about programming, Web development, Open Source, Linux and DevOps.

Go - Maps

A map is an unordered group of elements of one type that are indexed by keys of another type.

Declaration

The syntax to define a map is map[KeyType]ElementType.

The key type must be comparable (== and != defined for the type).

go
// Map with a key type of `string` and element type of `int`.
// The value of an uninitialized map is `nil`.
var m map[string]int // nil

Initialization

A map may be initialized using the map literal syntax.

go
// An empty (non-nil) map.
empty := map[string]bool{}

// A map literal specifying key-value pairs.
m := map[string]int{
  "a": 1,
  "b": 2,
  "c": 3,
}

// The element type can of any type even a `map`.
// Key type: `string` and element type: `map[string]int`.
mm := map[string]map[string]int{}

Or using the make() function.

go
// The `make` function returns an initialized empty map ready for use.
m := make(map[string]int) // map[string]int{}

// `make` accepts an optional capacity hint as the second argument.
// The initial capacity does not bound the map size.
// Maps grow to accommodate the number of items stored in them.
m = make(map[string]int, 100) // Initial capacity of 100

Map Elements

go
// Map of `int` values indexed by `string` keys.
m := make(map[string]int)

// Insert new elements in the map.
// The map grows as new elements are added.
m["a"] = 1
m["b"] = 2

// Get an element's value using the specified key.
a := m["a"] // 1

// Modify a value using the specified key.
m["a"] = 11

// Delete an element using the specified key.
delete(m, "a")
// `delete` is a no-op if the element does not exist.
delete(m, "x") // no-op

// The index expression yields a an additional `bool` value.
// that is `true` if the key is present in the map and `false` otherwise.
// If the key is not present the value will be the zero value of the element type.
v, ok := m["x"] // By convention the bool value is named `ok`

if ok {
  fmt.Println("The key x is present in the map")
} else {
  fmt.Println("The key x is not present in the map")
  fmt.Println(v) // 0 (zero value of the element type)
}
go
// A nil map.
var m map[string]int // nil

// No elements may be added to a nil map.
m["a"] = 1 // panic: assignment to entry in nil map

// Getting an element from a nil map returns the zero value
// of the element type.
a := m["a"]     // 0
b, ok := m["b"] // 0, false

// `delete` is a no-op if the map is nil.
delete(m, "a") // no-op

Map Length

A map’s length is the number of its elements and it may change as elements are added or deleted.

go
m := map[string]int{
  "a": 1,
  "b": 2,
  "c": 3,
}

len(m) // 3

m["d"] = 4 // Add an element

len(m) // 4

delete(m, "a") // Delete an element

len(m) // 3

Iteration

We can iterate over a map using a for range loop.

go
for key, value := range m {
  fmt.Printf("Key: %v, Value: %v\n", key, value)
}

Maps As Function Arguments

When maps are passed as function arguments, a reference is passed and not a copy of the map.

go
m := map[string]int{
  "a": 1,
  "b": 2,
  "c": 3,
}

func modifyMap(m map[string]int) {
  // Any changes made to the map inside the function will affect
  // the map and will be visible outside the function.
  m["a"] = 100
}

modifyMap(m)

fmt.Println(m["a"]) // 100