For loop

Go has only one looping construct, the for loop.

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

for i := 0; i < 10; i++ {
	sum += i

The init and post statement are optional. When both are omitted, it is essentially a while loop, and the semicolons can be dropped:

for sum < 1000 {
	sum += sum

Moreover, for { } is the infinite loop.


The range form of the for loop iterates over a slice or map.

When ranging over a slice, two values are returned for each iteration: the first is the index, and the second is a copy of the element at that index.

for index, value := range slice {

You can skip the index or value by assigning to _. If only the index is wanted, , value can be dropped entirely.

for _, value := range slice {

for index := range slice {

For strings, the range does more work for you, breaking out individual Unicode code points by parsing the UTF-8. Erroneous encodings consume one byte and produce the replacement rune U+FFFD. for pos, char := range "string" returns each Unicode rune and its byte position.


Go’s if statements are like its for loops; the expression need not be surrounded by parentheses ( ) but the braces { } are required.

The braces for else statements are also required.

In the Go libraries, you’ll find that when an if statement doesn’t flow into the next statement—that is, the body ends in break, continue, goto, or return—the unnecessary else is omitted.

f, err := os.Open(name)
if err != nil {
    return err

This is an example of a common situation where code must guard against a sequence of error conditions. The code reads well if the successful flow of control runs down the page, eliminating error cases as they arise. Since error cases tend to end in return statements, the resulting code needs no else statements.

If with a short statement

Like for, the if statement can start with a short statement to execute before the condition.

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

Variables declared by the statement are only in scope until the end of the if, including else if and else.

A more realistic usage is error handling:

if err := process(); err != nil {
  return err


Go’s switch is more like if-else-if-else chains than C-style switch. The expressions need not be constants or even integers, as they can be any boolean expressions or even comma-separated lists. Switch cases evaluate cases from top to bottom, stopping when a case succeeds. A default can be supplied at the end.

A case body breaks automatically, unless it ends with a fallthrough statement.

func unhex(c byte) byte {
    switch {
    case '0' <= c && c <= '9':
        return c - '0'
    case 'a' <= c && c <= 'f':
        return c - 'a' + 10
    case 'A' <= c && c <= 'F':
        return c - 'A' + 10
    return 0

func shouldEscape(c byte) bool {
    switch c {
    case ' ', '?', '&', '=', '#', '+', '%':
        return true
    return false

Like if, the expression need not be surrounded by parentheses ( ) but the braces { } are required. And a short statement can be supplied.

Switch with no condition

Switch without a condition is the same as switch true.

This construct can be a clean way to write long if-then-else chains.


A defer statement defers the execution of a function until the surrounding function returns.

The deferred call’s arguments are evaluated immediately, but the function call is not executed until the surrounding function returns.

Deferred function calls are pushed onto a stack. When a function returns, its deferred calls are executed in last-in-first-out order. However, The arguments to the deferred function (which include the receiver if the function is a method) are evaluated when the defer executes, not when the call executes.