Each place where a declaration occurs is called a block. Variables, constants, types, and functions declared outside any functions are placed in the package block. Within a function, every set of braces ({}) defines another block, and in a bit you will see that the control structures in Go define blocks of their own.
You can access an identifier defined in any outer block from within any inner block. This raises the question: what happens when you have a declaration with the same name as an identifier in a containing block? If you do that, you shadow the identifier created in the outer block.
func main() {
x := 10
if x > 5 {
fmt.Println(x) // 10
x := 5
fmt.Println(x) // 5
}
fmt.Println(x) // 10
}
!example1
A shadowing variable is a variable that has the same name as a variable in a containing block. For as long as the shadowing variable exists, you cannot access a shadowed variable.
You can also shadow the package or default functions:
package main
import (
"fmt"
)
func main() {
fmt.Println("hello")
fmt := "oops"
fmt.Println("hello")
}
$ go run ./...
./main.go:10:6: fmt.Println undefined (type string has no field or method Println)
The if
statement in Go is much like the if
statement in most programming languages.
n := rand.Intn(10)
if n < 5 {
fmt.Println("That's too low:", n)
} else if n > 5 {
fmt.Println("That's too big:", n)
} else {
fmt.Println("Perfect:", n)
}
Go adds is the ability to declare variables that are scoped to the condition and to both the if
and else
blocks.
if n := rand.Intn(10); n < 5 {
fmt.Println("That's too low:", n)
} else if n > 5 {
fmt.Println("That's too big:", n)
} else {
fmt.Println("Perfect:", n)
}
- C-style for with open parts
for i := 0; i < 10; i++ {
fmt.Println(i)
}
i := 0
for ; i < 10; i++ {
fmt.Println(i)
}
for i := 0; i < 10; {
fmt.Println(i)
if i % 2 == 0 {
i++
} else {
i+=2
}
}
i := 1
for i < 100 {
fmt.Println(i)
i=i*2
}
for {
fmt.Println("Hello")
}
- for-range
fibNums := []int{1, 1, 2, 3, 5, 8}
for i, v := range fibNums {
fmt.Println(i, v)
}
!example2
break
exits the loop immediately, just like the break
statement in other languages
i := 0
for {
if i == 5 {
break
}
i++
}
fmt.Println(i)
continue
keyword, which skips over the rest of the for loop’s body and proceeds directly to the next iteration
for i := 1; i <= 100; i++ {
if i%3 == 0 {
if i%5 == 0 {
fmt.Println("FizzBuzz")
} else {
fmt.Println("Fizz")
}
} else if i%5 == 0 {
fmt.Println("Buzz")
} else {
fmt.Println(i)
}
}
But it is not idiomatic
for i := 1; i <= 100; i++ {
if i%3 == 0 && i%5 == 0 {
fmt.Println("FizzBuzz")
continue
}
if i%3 == 0 {
fmt.Println("Fizz")
continue
}
if i%5 == 0 {
fmt.Println("Buzz")
continue
}
fmt.Println(i)
}
!example3
!example4
Most developers in those languages avoid switch
statements because of their limitations on values
that can be switched on and the default fall-through behavior. But Go is different.
It makes switch
statements useful.
words := []string{"a", "cow", "smile", "gopher", "octopus", "anthropologist"}
for _, word := range words {
switch size := len(word) {
case size < 5:
fmt.Println(word, "is a short word!")
case 5:
wordLen := len(word)
fmt.Println(word, "is exactly the right length:", wordLen)
case size > 10:
default:
fmt.Println(word, "is a long word!")
}
}
words := []string{"hi", "salutations", "hello"}
for _, word := range words {
switch wordLen := len(word); {
case wordLen < 5:
fmt.Println(word, "is a short word!")
case wordLen > 10:
fmt.Println(word, "is a long word!")
default:
fmt.Println(word, "is exactly the right length.")
}
}
!fallthrough
Write a for loop that puts 100 random numbers between 0 and 100 into a slice and prints it.
Loop over the slice you created in exercise 1. For each value in the slice, apply the following rules:
- If the value is divisible by 2, print “Two!”
- If the value is divisible by 3, print “Three!”
- If the value is divisible by 2 and 3, print “Six!”. Don’t print anything else.
- Otherwise, print “Never mind”.
Start a new program. In main, declare an int
variable called total
.
Write a for
loop that uses a variable named i
to iterate from 0
(inclusive) to 10
(exclusive).
The body of the for loop should be as follows:
total := total + i
fmt.Println(total)
After the for loop, print out the value of total
.