4 min read

Arrays and Slices in Go with Tests

Table of Contents

Hey there! ๐Ÿ‘‹ Today weโ€™re diving into arrays and slices in Go. Donโ€™t worryโ€”itโ€™s easier than assembling IKEA furniture. Letโ€™s break it down!

Arrays: The Strict Lunchbox ๐Ÿฑ

Arrays are like a lunchbox with fixed compartments.

You declare how many slots it has upfront:

// A lunchbox with 5 sandwich slots (zero if empty)
lunchbox := [5]int{1, 2, 3, 4, 5}

Key quirks:

  • Size is part of its type. [5]int โ‰  [4]int (Go wonโ€™t let you mix them).
  • Rigid. No extra sandwiches allowed. ๐Ÿ˜ค

Slices: The Flexible Backpack ๐ŸŽ’

Slices are dynamicโ€”like a backpack that grows as you stuff more in:

// A backpack with sandwiches (size adjusts automatically!)
backpack := []int{1, 2, 3}

Why slices rule:

  • โœ… No fixed size
  • โœ… Can append() more items
  • โœ… Can slice parts (e.g., backpack[1:] gives everything except the first item)

Letโ€™s TDD a Sum Function โž•

Step 1: Write the Test First ๐Ÿงช

func TestSum(t *testing.T) {
    numbers := []int{1, 2, 3}
    got := Sum(numbers)
    want := 6
    if got != want {
        t.Errorf("got %d want %d (numbers: %v)", got, want, numbers)
    }
}

Step 2: Make It Pass ๐Ÿƒโ€โ™‚๏ธ

func Sum(numbers []int) int {
    sum := 0
    for _, num := range numbers {  // _ ignores the index
        sum += num
    }
    return sum
}

Boom! Test passes. ๐ŸŽ‰

SumAll: Sum Multiple Slices ๐Ÿ”ข

What if we want to sum multiple slices?

Test:

func TestSumAll(t *testing.T) {
    got := SumAll([]int{1, 2}, []int{0, 9})
    want := []int{3, 9}
    if !reflect.DeepEqual(got, want) {  // Slices canโ€™t use ==
        t.Errorf("got %v want %v", got, want)
    }
}

Solution:

func SumAll(slices ...[]int) []int {
    var sums []int
    for _, slice := range slices {
        sums = append(sums, Sum(slice))
    }
    return sums
}

Pro Tip: ...[]int means โ€œaccept any number of slices.โ€

SumAllTails: Ignore the First Item ๐Ÿšซ๐Ÿž

Sometimes you just want the tail (everything except the first element).

Test:

func TestSumAllTails(t *testing.T) {
    t.Run("normal slices", func(t *testing.T) {
        got := SumAllTails([]int{1, 2}, []int{0, 9})
        want := []int{2, 9}
        checkSums(t, got, want)
    })

    t.Run("empty slices", func(t *testing.T) {
        got := SumAllTails([]int{}, []int{3, 4, 5})
        want := []int{0, 9}
        checkSums(t, got, want)
    })
}

Solution:

func SumAllTails(slices ...[]int) []int {
    var sums []int
    for _, slice := range slices {
        if len(slice) == 0 {
            sums = append(sums, 0)
        } else {
            tail := slice[1:]  // Take everything from index 1 onward
            sums = append(sums, Sum(tail))
        }
    }
    return sums
}

Watch out! Slicing an empty slice crashes. Always check len() first.

Key Takeaways ๐Ÿ—๏ธ

  • Arrays = Fixed size ([5]int).
  • Slices = Dynamic ([]int). Use append() to grow.
  • Slicing = slice[low:high] (e.g., slice[1:] = everything after index 0).
  • reflect.DeepEqual = Compares slices (but use carefullyโ€”itโ€™s not type-safe!).
  • Always handle empty slicesโ€”or risk runtime panics!

Now go forth and slice like a pro! ๐Ÿ•๐Ÿ”ช

Next Up: Structs, methods & interfaces โ€” where Go gets really fun. ๐Ÿš€

Support my open source work ๐Ÿš€

Let's Connect

I'm open to discussing new opportunities. Feel free to connect with me or send me an email at [email protected]