All Posts programming Learn Go | Tutorial 3: The Grocery List Problem

Learn Go | Tutorial 3: The Grocery List Problem

ยท 752 words ยท 4 minute read
go ▹

This tutorial turns your single status line into a small task list. You will meet slices and loops only because managing multiple tasks without them is painful.

Tutorial 3: The Grocery List Problem ๐Ÿ”—

When you have more than one task, creating task1, task2, task3 variables quickly becomes impossible to maintain. Go solves this with arrays and, more commonly, slices, which act like dynamic lists of items.

The goal of this tutorial is to create a hardcoded list of tasks and print them all nicely so Go-Getter starts to feel like a real checklist.

Step 1: Start from previous version ๐Ÿ”—

Begin with your latest main.go, which probably looks similar to this:

package main

import "fmt"

func main() {
    appName := "Go-Getter"
    version := "v0.1"
    status := "Online"

    fmt.Printf("%s %s: Status = %s\n", appName, version, status)
}

This prints one line of status, but says nothing about actual tasks you want to track, so you will evolve it into a list view.

Keep the appName, version, and status variables; you are only going to add task-related code below them.

Step 2: Why individual variables fail ๐Ÿ”—

Imagine trying to track three tasks like this:

task1 := "Buy groceries"
task2 := "Write Go-Getter spec"
task3 := "Read about Go slices"

You could print them one by one, but every new task means a new variable and a new print line, which becomes messy and unscalable as soon as you reach more than a handful of tasks.

This situation creates the “need” for a structure that holds many values of the same type under one name, which is where slices come in.

Step 3: Introduce slices for tasks ๐Ÿ”—

Go has fixed-size arrays, but in real programs slices are preferred because they can grow and shrink and are more convenient to work with.

Replace your individual task variables with a single slice of strings:

tasks := []string{
    "Buy groceries",
    "Write Go-Getter spec",
    "Read about Go slices",
    "Refactor status output",
    "Plan user input flow",
}

Here, []string means “a list of strings”, and the curly braces initialize the slice with five task values in order.

Place this block right after your status variables:

appName := "Go-Getter"
version := "v0.1"
status := "Online"

tasks := []string{
    "Buy groceries",
    "Write Go-Getter spec",
    "Read about Go slices",
    "Refactor status output",
    "Plan user input flow",
}

Step 4: Loop through the list ๐Ÿ”—

To print every task, you need a loop. Go’s for is the only loop keyword, and the for ... range form is perfect for walking through slices element by element.

Add this below your fmt.Printf status line:

fmt.Printf("%s %s: Status = %s\n", appName, version, status)
fmt.Println("Today's tasks:")

for i, task := range tasks {
    fmt.Printf("%d. %s\n", i+1, task)
}

In this loop:

  • range tasks walks over each element in the tasks slice.
  • i is the index (starting at 0), and task is the string at that position.
  • i+1 is used so the printed list starts from 1 instead of 0, which is friendlier for humans.

Your complete main.go now looks like:

package main

import "fmt"

func main() {
    appName := "Go-Getter"
    version := "v0.1"
    status := "Online"

    tasks := []string{
        "Buy groceries",
        "Write Go-Getter spec",
        "Read about Go slices",
        "Refactor status output",
        "Plan user input flow",
    }

    fmt.Printf("%s %s: Status = %s\n", appName, version, status)
    fmt.Println("Today's tasks:")

    for i, task := range tasks {
        fmt.Printf("%d. %s\n", i+1, task)
    }
}

Run it with go run main.go and you should see a numbered list of tasks under your status line.

Step 5: Mini-challenges to lock it in ๐Ÿ”—

Apply what you just learned by changing the program a bit:

  • Add a sixth task and confirm it shows automatically without changing any loop code.
  • Create another slice, completedTasks, with 2โ€“3 items and print a second section titled "Completed tasks:" using another for range loop.
  • Try removing i from for i, task := range tasks (use _ instead of i) and print tasks without numbers, to see how ignoring the index works.

In the next tutorial, the “annoyance” will be that your tasks are hardcoded, and that will create the need to read input from the user so tasks can be entered at program runtime.

I hope you enjoyed reading this post as much as I enjoyed writing it. If you know a person who can benefit from this information, send them a link of this post. If you want to get notified about new posts, follow me on YouTube , Twitter (x) , LinkedIn , and GitHub .

go ▹