Control Structures

Now that we know how to use variables it's time to start writing some useful programs. First let's write a program that counts to 10, starting from 1, with each number on its own line. Using what we've learned so far we could write this:

package main

import "fmt"

func main() {
  fmt.Println(1)
  fmt.Println(2)
  fmt.Println(3)
  fmt.Println(4)
  fmt.Println(5)
  fmt.Println(6)
  fmt.Println(7)
  fmt.Println(8)
  fmt.Println(9)
  fmt.Println(10)
}

Or this:

package main
import "fmt"

func main() {
  fmt.Println(`1
2
3
4
5
6
7
8
9
10`)
}

But both of these programs are pretty tedious to write. What we need is a way of doing something multiple times.

For

The for statement allows us to repeat a list of statements (a block) multiple times. Rewriting our previous program using a for statement looks like this:

package main

import "fmt"

func main() {
  i := 1
  for i <= 10 {
    fmt.Println(i)
    i = i + 1
  }
}

First we create a variable called i that we use to store the number we want to print. Then we create a for loop by using the keyword for, providing a conditional expression which is either true or false and finally supplying a block to execute. The for loop works like this:

The i = i + 1 line is extremely important, because without it i <= 10 would always evaluate to true and our program would never stop. (When this happens this is referred to as an infinite loop)

As an exercise let's walk through the program like a computer would:

Other programming languages have a lot of different types of loops (while, do, until, foreach, …) but Go only has one that can be used in a variety of different ways. The previous program could also have been written like this:

func main() {
  for i := 1; i <= 10; i++ {
    fmt.Println(i)
  }
}

Now the conditional expression also contains two other statements with semicolons between them. First we have the variable initialization, then we have the condition to check each time and finally we “increment” the variable. (adding 1 to a variable is so common that we have a special operator: ++. Similarly subtracting 1 can be done with --)

We will see additional ways of using the for loop in later chapters.

If

Let's modify the program we just wrote so that instead of just printing the numbers 1-10 on each line it also specifies whether or not the number is even or odd. Like this:

1 odd
2 even
3 odd
4 even
5 odd
6 even
7 odd
8 even
9 odd
10 even

First we need a way of determining whether or not a number is even or odd. An easy way to tell is to divide the number by 2. If you have nothing left over then the number is even, otherwise it's odd. So how do we find the remainder after division in Go? We use the % operator. 1 % 2 equals 1, 2 % 2 equals 0, 3 % 2 equals 1 and so on.

Next we need a way of choosing to do different things based on a condition. For that we use the if statement:

if i % 2 == 0 {
  // even
} else {
  // odd
}

An if statement is similar to a for statement in that it has a condition followed by a block. If statements also have an optional else part. If the condition evaluates to true then the block after the condition is run, otherwise either the block is skipped or if the else block is present that block is run.

If statements can also have else if parts:

if i % 2 == 0 {
  // divisible by 2
} else if i % 3 == 0 {
  // divisible by 3
} else if i % 4 == 0 {
  // divisible by 4
}

The conditions are checked top down and the first one to result in true will have its associated block executed. None of the other blocks will execute, even if their conditions also pass. (So for example the number 8 is divisible by both 4 and 2, but the // divisible by 4 block will never execute because the // divisible by 2 block is done first)

Putting it all together we have:

func main() {
  for i := 1; i <= 10; i++ {
    if i % 2 == 0 {
      fmt.Println(i, "even")
    } else {
      fmt.Println(i, "odd")
    }
  }
}

Let's walk through this program:

The remainder operator, while rarely seen outside of elementary school, turns out to be really useful when programming. You'll see it turn up everywhere from zebra striping tables to partitioning data sets.

Switch

Suppose we wanted to write a program that printed the English names for numbers. Using what we've learned so far we might start by doing this:

if i == 0 {
  fmt.Println("Zero")
} else if i == 1 {
  fmt.Println("One")
} else if i == 2 {
  fmt.Println("Two")
} else if i == 3 {
  fmt.Println("Three")
} else if i == 4 {
  fmt.Println("Four")
} else if i == 5 {
  fmt.Println("Five")
}

Since writing a program in this way would be pretty tedious Go provides another statement to make this easier: the switch statement. We can rewrite our program to look like this:

switch i {
case 0: fmt.Println("Zero")
case 1: fmt.Println("One")
case 2: fmt.Println("Two")
case 3: fmt.Println("Three")
case 4: fmt.Println("Four")
case 5: fmt.Println("Five")
default: fmt.Println("Unknown Number")
}

A switch statement starts with the keyword switch followed by an expression (in this case i) and then a series of cases. The value of the expression is compared to the expression following each case keyword. If they are equivalent then the statement(s) following the : is executed.

Like an if statement each case is checked top down and the first one to succeed is chosen. A switch also supports a default case which will happen if none of the cases matches the value. (Kind of like the else in an if statement)

These are the main control flow statements. Additional statements will be explored in later chapters.

Problems

← Previous Index Next →