Array and Slices

Table of Contents

Basics of [N]T (arrays) tutorial

var q [3]int = [3]int{1, 2, 3}
var r [3]int = [3]int{1, 2}

// if an “...” appears in place of the length, the length is determined by the initializers.
// The size must be a constant expression,
q := [...]int{1, 2, 3}

const (
    USD Currency = iota
    EUR
    GBP
    RMB
)

// Init with Index, value pairs.
// The pairs can appear in any order
symbol := [...]string{USD: "$", EUR: "€", GBP: "£", RMB: "¥"}

// Some can be omitted (defines [0, 0, ..., -1])
r := [...]int{99: -1}

Basics of []T (slices) tutorial

If you need to test whether a slice is empty, use len(s) == 0, not s == nil.
package main

import "fmt"

func reverse(s []int) {
    for i, j := 0, len(s)-1; i < j; i, j = i+1, j-1 {
        s[i], s[j] = s[j], s[i]
    }
}

func main() {
  a := [...]int{0, 1, 2, 3, 4, 5}
  reverse(a[:]) // modifies `a`
  fmt.Println(a)
}
[5 4 3 2 1 0]
The slice operator s[i:j]
  • Creates a new slice that refers to elements i through j-1 of the sequence s,
  • When omitted, i is 0, and j is len(s).
  • 0 ≤ i ≤ j ≤ cap(s)
  • Slicing beyond cap(s) causes a panic
  • Slicing beyond len(s) extends the slice, so the result may be longer than the original

How append() works discussion

func appendInt(x []int, y int) []int {
    var z []int
    zlen := len(x) + 1
    if zlen <= cap(x) {
        // There is room to grow.  Extend the slice.
        z = x[:zlen]
    } else {
        // There is insufficient space.  Allocate a new array.
        // Grow by doubling, for amortized linear complexity.
        zcap := zlen
        if zcap < 2*len(x) {
            zcap = 2 * len(x)
        }
        z = make([]int, zlen, zcap)
        copy(z, x)
    }
    z[len(x)] = y
    return z
}

As we cannot know when append() grows the underlying array, we can’t assume that the original slice refers to the same array as the resulting slice, nor that it refers to a different one.

a := [...]int{0, 1, 2, 3}
b := a[1:2]
fmt.Println(b)
c := append(b, 99)
fmt.Println(c)
// a is affected by `append()` on `b`
fmt.Println(a)
[1]
[1 99]
[0 1 99 3]

Test the equality of two slices howto

func isEqual(a, b []int) bool {
    if (a == nil) != (b == nil) {
        return false
    }

    if len(a) != len(b) {
        return false
    }

    for i := range a {
        if a[i] != b[i] {
            return false
        }
    }

    return true
}

Passing slices by value vs by pointer? discussion

It’s idiomatic to have functions like slice = doSomethingWithSlice(slice) and less so to see doSomethingWithSlice(&slice)

Iterate in reverse order howto

s := []int{5, 4, 3, 2, 1}
for i := len(s)-1; i >= 0; i-- {
    fmt.Printf(" %d", s[i])
}
1 2 3 4 5

Slice Tricks howto

Convert slice of strings to slice of int howto

import "strconv"

func sliceAtoi(sa []string) ([]int, error) {
    si := make([]int, 0, len(sa))
    for _, a := range sa {
        i, err := strconv.Atoi(a)
        if err != nil {
            return si, err
        }
        si = append(si, i)
    }
    return si, nil
}

Transform []int to string with one line howto

a := []int{1, 2, 3}
s := strings.Trim(fmt.Sprint(a), "[]")
fmt.Println(s)
1 2 3