Skip to content

Latest commit

 

History

History
executable file
·
311 lines (231 loc) · 6.12 KB

02.2.md

File metadata and controls

executable file
·
311 lines (231 loc) · 6.12 KB

02.2 - for, if, else, switch and defer

For

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)
    ...
}

++ and --

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

if

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

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 ifs.

// 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

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
}

switch

Similar to C switch with some differences:

  • Doesn't automatically go to the next switch statement unless you have fallthrough in the end. The fallthrough 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

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.