Differences between revisions 2 and 3
Revision 2 as of 2025-10-10 15:02:31
Size: 4194
Comment: Rewrite
Revision 3 as of 2025-10-10 15:11:43
Size: 4210
Comment: Link
Deletions are marked like this. Additions are marked like this.
Line 27: Line 27:
 * numeric  * [[Go/Numerics|numeric]]

Go Maps

Maps are a mapping data type. There is also a built-in maps module for working with the data type.


Type

Maps are a built-in implementation of a hash table. They associate values with keys.

Map types are pointers, so an uninitialized map is nil and cannot be used. Try:

// Uninitialized
var myMap map[int]string

// Initialized
myMap = make(map[int]string)

Keys must be one of the following types:

Usage

m := make(map[string]int)
m["a"] = 1
m["b"] = 2

m2 := map[string]int{"a": 1, "b": 2}

fmt.Println(m["a"]) //key exists, prints 1
fmt.Println(m["c"]) //key does not exist, prints the zero value

c, ok = m["c"]
if !ok {            //ok indicates if the key exists
    fmt.Println(c)
}

delete(m, "a")

for key, value := range m {
    fmt.Printf("%s = %s\n", key, value)
}

Range over a Map

The simplest and built-in way to range over a map is:

for key, value := range m {
    fmt.Printf("%s = %s\n", key, value)
}

In certain circumstances, it may be more efficient to import the maps module; see below.

Counter

A map can be used as a counter very easily. Because nonexistent keys return the zero value, it isn't necessary to check for existence.

counter := make(map[string]int)
for i = 0; i < len(mylist); i++ {
    counter[mylist[i]]++
}

Set

A map can be used as a set. The key is to use a value type that does not occupy any space in memory.

set := make(map[string]struct{})

set["a"] = struct{}
set["b"] = struct{}

delete(set, "a")

// Intersection
intersect := make(map[string]struct{})
for k, _ := range set {
    if anotherset[k] {
        intersect[k] = struct{}
    }
}

// Union
union := make(map[string]struct{})
for k, _ := range set {
    union[k] = struct{}
}
for k, _ := range anotherset {
    union[k] = struct{}
}

// In-place union
for k, _ := range anotherset {
    set[k] = struct{}
}

Notes

A map has to be either declared with make or initialized with a map literal, because the zero value of a map is nil.

Any comparable type can be used as the key in a map. This includes:

  • basic types like strings and integers
  • pointers
  • structs
  • channels
  • interfaces

The most notable types not allowed are slices and maps themselves.


Module

The following iteration functions are available. These can be more efficient or appropriate that the built-in method of ranging over a map.

Function

Return Value

Example

maps.All(m)

iterator

for key, value := maps.All(m) ...

maps.Keys(m)

iterator

for key := maps.Keys(m) ...

maps.Values(m)

iterator

for value := maps.Values(m) ...

Note that an iterator is perfect for ranging over, or for passing to another function that is prepared to handle any generic sequence (e.g. slices.Collect), but is not the same as a slice.

There are also the following constructor functions:

  • maps.Clone(m) for creating a new map from another map

  • maps.Collect(s) for creating a new map from an iterator of pairs (such as what is created by maps.All(m))

There are also some modification functions.

  • maps.Copy(dest, src) sets keys and values into a destination map according to a source map

  • maps.DeleteFunc(m, func) deltes keys programmatically

  • maps.Insert(m, s) sets keys and values into a map according to an iterator of pairs

There are two functions for checking equality. maps.Equal(m1, m2) uses built-in equality while maps.EqualFunc(m1, m2, func) uses a user-provided function to check equality of values. Keys are checked using built-in equality still.


CategoryRicottone

Go/Maps (last edited 2025-10-10 15:11:43 by DominicRicottone)