Chapter 4 of 20
Control Flow
if / for / switch / defer
if Statements
Conditions don't need parentheses; you can declare a local variable inside the if.
package main
import (
"fmt"
"strconv"
)
func main() {
s := "42"
if v, err := strconv.Atoi(s); err == nil {
fmt.Println("num:", v)
} else {
fmt.Println("not a number")
}
}for Loops
Go has only for, but it expresses four forms: the C-style three-part loop, while, an infinite loop, and range.
package main
import "fmt"
func main() {
// three-part form
for i := 0; i < 3; i++ {
fmt.Println(i)
}
// while style
n := 3
for n > 0 {
n--
}
fmt.Println("n=", n)
// infinite loop + break
i := 0
for {
if i >= 2 {
break
}
i++
}
// range: index + value
for i, v := range []int{10, 20, 30} {
fmt.Println(i, v)
}
}switch
No fall-through by default; any expression can serve as a case, and fallthrough opts into explicit fall-through. The expression-less form can replace an if-else chain.
package main
import (
"fmt"
"time"
)
func main() {
switch day := time.Now().Weekday(); day {
case time.Saturday, time.Sunday:
fmt.Println("weekend")
default:
fmt.Println("workday")
}
// expression-less form: replaces an if-else chain
score := 85
grade := "F"
switch {
case score >= 90:
grade = "A"
case score >= 60:
grade = "B"
}
fmt.Println("grade:", grade)
}defer
defer postpones a statement until just before the enclosing function returns, in last-in-first-out order. Commonly used to release resources.
package main
import (
"fmt"
"os"
)
func main() {
if err := readFile("/etc/hostname"); err != nil {
fmt.Println("err:", err)
}
}
func readFile(path string) error {
f, err := os.Open(path)
if err != nil {
return err
}
defer f.Close() // called automatically before the function returns
info, err := f.Stat()
if err != nil {
return err
}
fmt.Println(info.Name(), info.Size())
return nil
}break / continue / goto
Labeled break/continue can jump out of nested loops; goto still exists but is rarely used.