Learn Go | Tutorial 3: The Grocery List Problem
- Part 1: Learn Go | Tutorial 1 (The Handshake): Your First Go Program
- Part 2: Learn Go | Tutorial 2: Storing a Thought (Variables)
- Part 3: Learn Go | Tutorial 3: The Grocery List Problem
- Part 4: Learn Go | Tutorial 4: Listening to the User
- Part 5: Learn Go | Tutorial 5: Making Choices (The Command Loop)
- Part 6: Learn Go | Tutorial 6: The Memory Loss Issue (File Persistence)
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 taskswalks over each element in thetasksslice.iis the index (starting at 0), andtaskis the string at that position.i+1is 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 anotherfor rangeloop. - Try removing
ifromfor i, task := range tasks(use_instead ofi) 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 .
- Part 1: Learn Go | Tutorial 1 (The Handshake): Your First Go Program
- Part 2: Learn Go | Tutorial 2: Storing a Thought (Variables)
- Part 3: Learn Go | Tutorial 3: The Grocery List Problem
- Part 4: Learn Go | Tutorial 4: Listening to the User
- Part 5: Learn Go | Tutorial 5: Making Choices (The Command Loop)
- Part 6: Learn Go | Tutorial 6: The Memory Loss Issue (File Persistence)