Skip to content

Collections

Make

The make keyword is used to create slices, maps, and channels that are initialized and ready for use. For example, a slice is a three component object with a pointer to an array, a length, and a capacity. Until these are set, the slice is considered nil. The make keyword initialized these variables and makes the slice ready to use. It also returns value of type T instead of a pointer with new.

Arrays

Arrays in Go are fixed length and must be declared at initialization.

go
var a [10]int
a[0] = 1

Slices

A slice is like an array but it does not have a fixed size. You can further slice a slice be specifying a low and high index, inclusive of the first and exclusive of the last.

go
primes := [6]int{2, 3, 5, 7, 11, 13}

var s []int = primes[1:4]
fmt.Println(s) // 3 5 7
s = primes[3:] // 7, 11, 13
s = primes[:2] // 2, 3

Slices are references to an underlying array, so if you create a slice of an array and edit that slice, you will also edit the underlying array.

go
names := [4]string{
		"John",
		"Paul",
		"George",
		"Ringo",
	}
	fmt.Println(names) // John Paul George Ringo

	a := names[0:2]
	b := names[1:3]
	fmt.Println(a, b) // John Paul, Paul George

	b[0] = "XXX"
	fmt.Println(a, b) // John XXX, XXX George
	fmt.Println(names) // John XXX George Ringo

Length vs Capacity

The length of a slice is how many items are actually stored in the array, and the capacity is how many slots the array has. A slice is considered a nil slice if it has 0 length and capacity and no underlying array.

go
package main

import "fmt"

func main() {
	s := []int{2, 3, 5, 7, 11, 13}
	printSlice(s)

	// Slice the slice to give it zero length.
	s = s[:0]
	printSlice(s)

	// Extend its length.
	s = s[:4]
	printSlice(s)

	// Drop its first two values.
	s = s[2:]
	printSlice(s)
}

func printSlice(s []int) {
	fmt.Printf("len=%d cap=%d %v\n", len(s), cap(s), s)
}

// Output
// len=6 cap=6 [2 3 5 7 11 13]
// len=0 cap=6 []
// len=4 cap=6 [2 3 5 7]
// len=2 cap=4 [5 7]

You can create slices with specific length and capacity using make.

go
x := make([]int, 0, 5) // len(x)=0, cap(x)=5

x = x[:cap(x)] // len(x)=5, cap(x)=5
x = x[1:]      // len(x)=4, cap(x)=4

a := make([]int, 5)
// a len=5 cap=5 [0 0 0 0 0]

b := make([]int, 0, 5)
// b len=0 cap=5 []

c := b[:2]
// c len=2 cap=5 [0 0]

d := c[2:5]
// d len=3 cap=3 [0 0 0]

Appending

If the underlying array of the slice is too small to accommodate the new elements, the returned slice will point to a newly allocated array.

go
var s []int
// len=0 cap=0 []

// append works on nil slices.
s = append(s, 0)
// len=1 cap=1 [0]

// The slice grows as needed.
s = append(s, 1)
// len=2 cap=2 [0 1]

// We can add more than one element at a time.
s = append(s, 2, 3, 4)
// len=5 cap=6 [0 1 2 3 4]

Maps

Maps are key-value pairs. They can be created with make.

go
package main

import "fmt"

type Vertex struct {
	Lat, Long float64
}

var m map[string]Vertex // cannot be used

func main() {
	m = make(map[string]Vertex) // now can be used
	m["Bell Labs"] = Vertex{
		40.68433, -74.39967,
	}
	fmt.Println(m["Bell Labs"])

    // Map literal
    var n = map[string]Vertex{
        "Bell Labs": Vertex{
            40.68433, -74.39967,
        },
        "Google": Vertex{
            37.42202, -122.08408,
        },
    }

    // Shorthand
    var o = map[string]Vertex{
        "Bell Labs": {40.68433, -74.39967},
        "Google":    {37.42202, -122.08408},
    }
}

Manipulating the map

go
m[key] = elem
elem = m[key]
delete(m, key)

// Check if element exists
elem, ok = m[key]