Similar to C with two differences:
- No parenthesis around the three components. Having parenthesis will give result in an error.
- Curly braces
{ }
are always required and the first one needs to be in the same line as for, if, etc.
It has three components:
for init; condition; post { }
// 02.2-01-for1.go
package main
import "fmt"
func main() {
// var sum int
sum := 0
for i := 0; i < 20; i++ {
sum += i
}
fmt.Println(sum)
}
Init and post (first and last) components are optional and turn for
into while
:
// 02.2-02-for2.go
package main
import "fmt"
func main() {
// var sum int
sum, i := 0
for i < 20 { // while (i<20)
sum += i
i++
}
fmt.Println(sum)
}
Without the condition it turns into for(;;)
or while(1)
for { // while(1)
...
}
Don't be fooled by their use in for
examples. According to the FAQ, they are "statements" and not "expressions." In other words we can use them to increase or decrease a variable by one but cannot assign the result to a different one.
This will not work:
// 02.2-03-incdec.go
package main
import "fmt"
func main() {
// var sum int
sum, i := 0
// This will not work
sum = i++
fmt.Println(sum)
}
Z:\Go\src\Hacking-with-Go\code\02>go run 02.2-03-incdec.go
# command-line-arguments
.\02.2-03-incdec.go:9:9: syntax error: unexpected ++ at end of statement
Does not need parenthesis but needs curly braces.
// 02.2-04-if1.go
package main
import "fmt"
func main() {
a := 10
b := 20
if b > a {
fmt.Println(b, ">", a)
}
}
Short statements are interesting. They are statements that are executed before the condition. It's not a unique idea to Go because we have already seen them in for
constructs in almost every language.
They can be used in if
s.
// 02.2-05-if2.go
package main
import "fmt"
func main() {
if var1 := 20; var1 > 10 {
fmt.Println("Inside if:", var1)
}
// Cannot use the variable var1 here
}
In this code var1 := 20
is executed before the if
condition. Any variables declared in the short statement are only in scope in the if
block and are destroyed after.
Short statements are usually used for executing a function and checking the return value with an if
.
else
is similar to C else.
If the corresponding if
has a short statement then any variables declared in the short statement are also in scope in the else
block.
// 02.2-06-else.go
package main
import "fmt"
func main() {
if var1 := 20; var1 > 100 {
fmt.Println("Inside if:", var1)
} else {
// Can use var1 here
fmt.Println("Inside else:", var1)
}
// Cannot use var1 here
}
Similar to C switch with some differences:
- Doesn't automatically go to the next
switch
statement unless you havefallthrough
in the end. Thefallthrough
only works if it's the last statement in the case. - Can have a short statement like
if
.
// 02.2-07-switch1.go
package main
import (
"fmt"
"math/rand" // This is not cryptographically secure!
"time"
)
func main() {
// Seeding rand
rand.Seed(time.Now().UnixNano())
fmt.Println("Choosing a random number:")
switch num := rand.Intn(3); num {
case 1:
fmt.Println("1")
case 2:
fmt.Println("2")
default:
fmt.Println("3")
}
}
Cases can have if
conditions if we use a switch with an empty value:
// 02.2-08-switch2.go
package main
import (
"fmt"
"math/rand" // This is not cryptographically secure!
"time"
)
func main() {
// Seeding rand
rand.Seed(time.Now().UnixNano())
fmt.Println("Choosing a random number:")
switch num := rand.Intn(100); {
case num < 50:
fmt.Println("Less than 50")
default:
fmt.Println("More than 50")
}
}
The short statement does not have to be part of the switch:
// 02.2-09-switch3.go
package main
import (
"fmt"
"math/rand" // This is not cryptographically secure!
"time"
)
func main() {
// Seeding rand
rand.Seed(time.Now().UnixNano())
fmt.Println("Choosing a random number:")
num := rand.Intn(100)
switch {
case num < 50:
fmt.Println("Less than 50")
default:
fmt.Println("More than 50")
}
}
defer
is another interesting feature in Go. It defers the execution of a function until the calling function returns.
It works like a stack, every time program reaches a defer
, it will push that function with its argument values. When surrounding function returns, deferred functions are popped from the stack and executed.
// 02.2-10-defer1.go
package main
import "fmt"
func main() {
defer fmt.Println("This runs after main")
fmt.Println("Main ended")
}
Results in:
Z:\Go\src\Hacking-with-Go\code\02>go run 02.2-10-defer1.go
Main ended
This runs after main
Argument values are saved when the defer
statement is reached but it is executed later.
// 02.2-11-defer2.go
package main
import "fmt"
func main() {
num := 1
defer fmt.Println("After main returns", num)
num++
fmt.Println("Inside main", num)
}
$ go run 02.2-11-defer2.go
Inside main 2
After main returns 1
The value of num
was 1
when the print was deferred.