Decision Statement

The decision statement in Go like in many other languages is the “if” statement. This statement is using a conditional expression that evaluate to a Boolean value. When the value is true the next statement or block of statements is executed otherwise is not executed and skipped over.

The condition do not have to be included in parentheses ( ) like in some other programming languages. After the condition we use braces { } that are mandatory to create a block of code with several statements.

Example of decision with a single block:

package main

import (
	"fmt"
	"math"
)

func sqrt(x float64) string {
	if x < 0 {
		return sqrt(-x) + "i"
	}
	return fmt.Sprint(math.Sqrt(x))
}

func main() {
	fmt.Println(sqrt(2), sqrt(-4))
}

The local scope

The “if” statement has a local scope. That is we can define a local “control variable” to be used inside the if block. That may be harder to comprehend. In the next example variable v is in to local scope of the “if” statement.  Variables declared by the statement are only in scope until the end of the “if”.  If we try using v after the last return statement we will have an error.

Example of local scope:

package main

import (
	"fmt"
	"math"
)

func pow(x, n, lim float64) float64 {
	if v := math.Pow(x, n); v < lim {
		return v
	}
	return lim
}

func main() {
	fmt.Println(
		pow(3, 2, 10),
		pow(3, 3, 20),
	)
}

Two path decisions

For creation of two blocks of code in decision statement we use “else” keywordThis is also known as two deck conditional statement. Variables declared inside an “if” simple statement are also available inside “else” block.

package main

import (
    "fmt"
    "math"
)

func pow(x, n, lim float64) float64 {
    if v := math.Pow(x, n); v < lim { 
        return v 
    } else { 
        fmt.Printf("%g >= %g\n", v, lim)
    }
    // can't use v here, though
    return lim
}

func main() {
    fmt.Println(
        pow(3, 2, 10),
        pow(3, 3, 20),
    )
}

Iteration

Go use only one keyword for all iterations: the “for” keyword. This can define a finite or infinite loop.

Basic loop

The basic “for loop” has three components separated by semicolons:

  1. the init statement: executed before the first iteration
  2. the condition expression: evaluated before every iteration
  3. the post statement: executed at the end of every iteration

The init statement will often be a short variable declaration, and the variables declared there are visible only in the scope of the for statement. The loop will stop iterating once the Boolean condition evaluates to false. The “init” and “post” statement are optional.

package main

import "fmt"

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

Note: Unlike other languages like C, Java, or Javascript there are no parentheses surrounding the three components of the  for statement. The braces { } are always required.

Example of for with no “init: and no “post”. It may be curios how the single semicolon is still necessary. So it looks like a conditional between two semicolons.

package main

import "fmt"

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

The while loop

To simulate a while loop we use for with a post conditional  and no control variable:

package main

import "fmt"

func main() {
	sum := 1
	for sum < 1000 {
		sum += sum
	}
	fmt.Println(sum)
}

Infinite loop

To simulate an infinite iteration we use a for loop with no condition and no control variable:

package main

func main() {
   for { }
}

Switch

The switch statement is a multi-path conditional selection statement. This allow program to execute on different logical path depending on value of one variable. A switch statement use 2 multiple keywords to create a multi-case construct. The keywords are: {switch, case, default, fallthrough}

Value based switch

The switch use a control variable that is local to the case statement. In next example we use “os” variable to analyze the operating system. Switch cases evaluate cases from top to bottom, stopping when a case succeeds.

package main

import (
	"fmt"
	"runtime"
)

func main() {
	fmt.Print("Go runs on ")
	switch os := runtime.GOOS; os {
	case "darwin":
		fmt.Println("OS X.")
	case "linux":
		fmt.Println("Linux.")
	default:
		// freebsd, openbsd,
		// plan9, windows...
		fmt.Printf("%s.", os)
	}
}

When a case control variable has a particular case value switch breaks automatically and no other case is executed except when the case last statement is a fallthrough statement. The last is the “default” case is executed when variable has a different value from any other cases.

Conditional switch

Switch without a condition is the same as “switch true”. This switch can be used to create a multi-deck conditional construct similar to multiple cascading if statements. This construct can be a clean way to write long if-then-else chains.

package main

import (
	"fmt"
	"time"
)

func main() {
	t := time.Now()
	switch {
	case t.Hour() < 12:
		fmt.Println("Good morning!")
	case t.Hour() < 17:
		fmt.Println("Good afternoon.")
	default:
		fmt.Println("Good evening.")
	}
}

Errors

One Go program can execute normally or can have and error. Go programs create error state with “error” values. Functions often return a value of type “error”. Calling code should handle errors by testing whether the “error” equals nil value. The error type is a built-in interface similar to fmt.Stringer;

type error interface {
    Error() string
}

As with fmt.stringer the fmt package looks for the error interface when printing values.

i, err := strconv.Atoi("42")
if err != nil {
    fmt.Printf("couldn't convert number: %v\n", err)
    return
}
fmt.Println("Converted integer:", i)

A nil error denotes success; a non-nil  error denotes failure.

package main

import (
	"fmt"
	"time"
)

type MyError struct {
	When time.Time
	What string
}

func (e *MyError) Error() string {
	return fmt.Sprintf("at %v, %s",
		e.When, e.What)
}

func run() error {
	return &MyError{
		time.Now(),
		"it didn't work",
	}
}

func main() {
	if err := run(); err != nil {
		fmt.Println(err)
	}
}