todo Read https://go.dev/blog/maps #todo Watch https://www.youtube.com/watch?v=Tl7mi9QmLns

Map type is map[keyType]valueType.

Init

var x map[string]int // nil

Using map literal

y := map[string]int{} // empty map literal
q := map[string]string{ // nonempty map literal
	"key-1": "value-1",
	"key-2": "value-2",
}
var m = map[string]Vertex{
	"Bell Labs": Vertex{
		40.68433, -74.39967,
	},
	"Google": Vertex{
		37.42202, -122.08408,
	},
}
// Type name can be omitted
var m = map[string]Vertex{
	"Bell Labs": {40.68433, -74.39967},
	"Google":    {37.42202, -122.08408},
}

Comma after the last element in the map literal is required, contrary to some other languages, where it’s recommended, but not enforced.

Using make

messages := make(map[string]string)

When you don’t know values, but know how much keys will be there, you can specify the size to improve performance.

ages := make(map[int][]string, 10)

Example

package main
 
import "fmt"
 
type Vertex struct {
	Lat, Long float64
}
 
var m map[string]Vertex
 
func main() {
	m = make(map[string]Vertex)
	m["Bell Labs"] = Vertex{
		40.68433, -74.39967,
	}
	fmt.Println(m["Bell Labs"])
}

nil, zero value

The zero value of a map is nil.

var nilMap map[string]int
  • It has len=0, has no keys.
  • Read attempts will always return the zero value of the map’s value type.
  • Write attempts to a nil map causes a panic.

Comma ok idiom

Go doesn’t raise an error when you try to access the key that isn’t in the map. Instead it returns a zero value of the map’s element type. Go provides a comma ok idiom for cases when you need to know if the key is present in the map:

elem, ok := m[key]
// or if vars were initialized
elem, ok = m[key]

If key is in m, ok is true. If not, ok is false. If key is not in the map, then elem is the zero value for the map’s element type.

Delete from the map

delete(m, key)

If the key is not in the map or the map is nil, nothing happens.

Empty the map

clear(m)

Comparison

maps package provides maps.Equal() and maps.EqualFunc().

Using maps as sets

Go doesn’t have a separate set type. You can simulate some of its features you can use maps with key for the type you want to put into set, and use the bool for the value type.

intSet := map[int]bool{}
vals := []int{5, 10, 2, 5, 8, 7, 3, 9, 1, 2, 10}
for _, v := range vals {
    intSet[v] = true
}
fmt.Println(len(vals), len(intSet))
fmt.Println(intSet[5])
fmt.Println(intSet[500])
if intSet[100] {
    fmt.Println("100 is in the set")
}

Same idea with structs:

intSet := map[int]struct{}{}
vals := []int{5, 10, 2, 5, 8, 7, 3, 9, 1, 2, 10}
for _, v := range vals {
    intSet[v] = struct{}{}
}
if _, ok := intSet[5]; ok {
    fmt.Println("5 is in the set")
}

The advantage is that an empty struct uses zero bytes, while a boolean uses one byte. The disadvantage is that using a struct{} makes your code clumsier. You have a less obvious assignment, and you need to use the comma ok idiom to check if a value is in the set

There are also third-party libraries for that.