Skip to content

Latest commit

 

History

History
178 lines (134 loc) · 4.03 KB

File metadata and controls

178 lines (134 loc) · 4.03 KB

Container Types

Concepts

Arrays

Arrays in go operate like arrays in many other compiled languages. The size is built-in to the type, and to grow an array you must create a larger one and copy all the values.

...

func main() {
    var x [4]int
    var y [4]int = [4]int{1,2}
    fmt.Println(x, y)
    x[0] = 1
    x[3] = 9
    fmt.Println(x)
}
  • You declare an array by prepending the type with [N] where N is the length of the array.
  • When the array x was declared, the memory of it was allocated and each entry was initialized to its zero-value.
  • You can get or set an element of an array by indexing into it (x[0], for example).
  • You can assign to the whole (or partial, starting from the beginning) array by creating an array literal (ex. [4]int{1,2,3}).
  • Unlike c, go will panic if you try to index outside of the array.

Slices

While arrays have the type [N]type, slices have the tye []type, allowing them to grow.

To create a slice with an initial length of zero:

...

func main() {
    var x []int
    fmt.Println(x)
    x = append(x, 1)
    x = append(x, 2)
    x[0] = -1
    fmt.Println(x)
}

append only works for slices, not arrays.

Under the hood, a slice is a pointer to an array, a length, and a capacity. append will simply increase the length until it hits capacity, at which point it will make a new larger array and copy data to it.

To see the capacity, use the cap function.

To create slices with different lengths and capacity, use make.

...

func main() {
    var x []int = make([]int, 4) // length = 4, (inferred capacity = 4)
    y := make([]int, 4, 10) // length = 4, capacity = 10
    fmt.Println(cap(x), cap(y))
    x = append(x, 1)
    y = append(y, 1)
    fmt.Println(x, y)
}

When do you want to use length?

  • If you want to assign using indexes up to the length.

When do you want to use capacity?

  • When you know around how large your slice will be and want to increase performance.

Maps

Maps have the type map[N]M where N is the key type, and M is the value type. There is no mixing types in go maps. Additionally, the zero-value of a map is nil, so maps must be initialized with make or a map literal to write to them.

...

func main() {
    m := make(map[string]int) //empty map
    n := map[string]int{
        "books": 4,
        "movies": 7,
    }
    m["shows"] = 4
    fmt.Println(m, n)
}

When you index into a map with a value that isn't present, it evaulates to the zero-value of the type. You can also check that the value exists:

...

func main() {
    m := map[string]int {
        "a": 1,
        "b": 2,
    }
    c := m["c"]
    fmt.Println(c)

    d, ok := m["d"]
    fmt.Println(d, ok)
}

Iterating

Now that we have arrays, slices, and maps, let's look at how we can iterate through them.

...

func main() {
    x := [4]int{1, 2}
    y := []int{3, 4, 5}
    z := map[string]int{"a": 1, "b": 2}

    for i, el := range x {
        fmt.Println(i, el)
    }
    for i, el := range y {
        fmt.Println(i, el)
    }
    for k, v := range z {
        fmt.Println(k, v)
    }
}

You can also iterate through just the indices of the list or slice and keys of the map:

...

func main() {
    ...

    for i := range x {
        fmt.Println(i)
    }
    for k := range z {
        fmt.Println(k)
    }
}

If you would like to iterate through just the values of a list or map, use _:

...

func main() {
    ...

    for _, el := range x {
        fmt.Println(el)
    }
    for _, val := range z {
        fmt.Println val
    }
}

Exercises

Create a slice of lists of maps.

Tips

Lists are used less frequently than slices. If you're having trouble deciding, use a slice.

Further Reading

If you're feeling adventurous, this is a great read on the implementation of golang (and C++ and Java) maps.


prev -- up