The best part of programming in GO is that there are not multiple ways of doing standard things and that makes reading code and understanding it easier. But at the same time as we saw in previous post GO follows different conventions which needs to be understood.
for Loop
The for loop construct, is the only way for looping. Unlike other languages GO does not have familiar constructs like while, do-while etc. Let us look at the traditional for loop
func main() { for i := 0; i < 10; i++ { fmt.Println("Value of i =", i) } }
http://play.golang.org/p/bo7OjUCcBE
Output:
Value of i = 0
Value of i = 1
Value of i = 2
Value of i = 3
Value of i = 4
Value of i = 5
Value of i = 6
Value of i = 7
Value of i = 8
Value of i = 9
An alternative to do the same thing is shown below:
func main() { i := 0 for i < 10 { fmt.Println("Value of i =", i) i++ } }
http://play.golang.org/p/6wSSofaQV4
Key thing to note here is that, the for loop only has a condition and does not need preceding and following semicolons. GO is good enough to understand this syntax.
if-else
The behavior of if-else block is the same as in any other language.
func main() { p, q := 10, 20 if p < q { fmt.Println("q is greater than p") } else if p < q { fmt.Println("p is greater than q") } else { fmt.Println("q and p are equal") } }
http://play.golang.org/p/St4dklsD2l
Output:
q is greater than p
goto
GO supports goto statement. As the name says it all, this statement can be used to transfer control to particular point in the program.
func main() { i := 0 for ; i < 10; i++ { if i == 5 { goto Print } else if i > 5 { fmt.Println("Value of i =", i) } } Print: fmt.Println("Value of i =", i) }
http://play.golang.org/p/s7vxx3fUfS
Output:
Value of i = 5
In for loop we are checking if value of i is 5, then take the control outside for loop i.e. it will break out of the for loop and will print value of i.
break-continue
The keywords break and continue work in the same was as they do in other languages. The keyword break is for breaking the loop and continue is for skipping the code and moving back to next iteration. In addition to this in GO, break and continue also support a label.
break
func main() { flag := true OuterLoop: for i := 0; i < 5; i++ { for j := 0; j < 5; j++ { if i == 2 { if flag { break } else { break OuterLoop } } fmt.Println("Value of i:j -->", i, ":", j) } } }
http://play.golang.org/p/hCnU9V08O1
Here, we have couple of for loops. The first for loop will loop five times from 0 to 4. In the second for loop we have check if value of i (from outer for loop) is 2. If yes, then it checks for the Boolean variable flag. If flag is true, it will execute break statement and if false will execute break with label OuterLoop. For using break with label, the label needs be set on for, switch or select statements.
Output(flag=true):
Value of i:j –> 0 : 0
Value of i:j –> 0 : 1
Value of i:j –> 0 : 2
Value of i:j –> 0 : 3
Value of i:j –> 0 : 4
Value of i:j –> 1 : 0
Value of i:j –> 1 : 1
Value of i:j –> 1 : 2
Value of i:j –> 1 : 3
Value of i:j –> 1 : 4
Value of i:j –> 3 : 0
Value of i:j –> 3 : 1
Value of i:j –> 3 : 2
Value of i:j –> 3 : 3
Value of i:j –> 3 : 4
Value of i:j –> 4 : 0
Value of i:j –> 4 : 1
Value of i:j –> 4 : 2
Value of i:j –> 4 : 3
Value of i:j –> 4 : 4
In this case the boolean variable flag is true, and hence break will be executed. If you look at the output, you can see iteration for i = 2 is missing. This is because as per the condition, if i == 2 and flag is true, break will be executed and hence, inner for loop will be break, but the outer for loop is still on and hence only iteration for 2 is skipped.
Now if you set flag to false, you will get the following output:
Output(flag=false):
Value of i:j –> 0 : 0
Value of i:j –> 0 : 1
Value of i:j –> 0 : 2
Value of i:j –> 0 : 3
Value of i:j –> 0 : 4
Value of i:j –> 1 : 0
Value of i:j –> 1 : 1
Value of i:j –> 1 : 2
Value of i:j –> 1 : 3
Value of i:j –> 1 : 4
Here, since flag is false, break with label is executed and control moves out of both for loops.
Similarly continue can also have label.
continue
func main() { flag := true OuterLoop: for i := 0; i < 5; i++ { for j := 0; j < 5; j++ { if j == 2 { if flag { continue } else { continue OuterLoop } } fmt.Println("Value of i:j -->", i, ":", j) } } }
http://play.golang.org/p/G7wtRJl3HK
Output(flag=true):
Value of i:j –> 0 : 0
Value of i:j –> 0 : 1
Value of i:j –> 0 : 3
Value of i:j –> 0 : 4
Value of i:j –> 1 : 0
Value of i:j –> 1 : 1
Value of i:j –> 1 : 3
Value of i:j –> 1 : 4
Value of i:j –> 2 : 0
Value of i:j –> 2 : 1
Value of i:j –> 2 : 3
Value of i:j –> 2 : 4
Value of i:j –> 3 : 0
Value of i:j –> 3 : 1
Value of i:j –> 3 : 3
Value of i:j –> 3 : 4
Value of i:j –> 4 : 0
Value of i:j –> 4 : 1
Value of i:j –> 4 : 3
Value of i:j –> 4 : 4
In this case flag is true and since j == 2, if you look at the output value if j as 2 is always skipped.
Now if you set flag to false, output will be:
Output(flag=false):
Value of i:j –> 0 : 0
Value of i:j –> 0 : 1
Value of i:j –> 1 : 0
Value of i:j –> 1 : 1
Value of i:j –> 2 : 0
Value of i:j –> 2 : 1
Value of i:j –> 3 : 0
Value of i:j –> 3 : 1
Value of i:j –> 4 : 0
Value of i:j –> 4 : 1
Since we have a condition on j == 2 and flag is set to false, continue with label is executed and when j = 2 in each iteration, control flows back to start of outer for loop and hence only 2 values of j are printed for each value of i.
switch
We all know switch can be used for multi-way expression. Again in GO, the way switch is implemented is slightly different and in my personal opinion the best. Let us look at an example to see how it is done is GO and why I think it is better.
func main() { x := 0 switch x { case 0: fmt.Println("Value of x =", 0) case 1: fmt.Println("Value of x =", 1) case 2: fmt.Println("Value of x =", 2) default: fmt.Println("Default") } }
http://play.golang.org/p/CVRkNVnWi_
Here, switch will evaluate value of x to find the matching case. We have set x as 0, so case 0 will be matched and executed. And now comes the best part. only case 0 will be executed that’s it. Unlike other languages if you don’t specify a break, the case statements that follow it are also executed.
From your experience with other programming languages and using switch statement in them, you know that 90% of the time, you need to execute only one case. Rarely you need to fall through cases. So you end up explicitly writing break statement for each case, and if you forget to do so chances are some unwanted cases to get executed. But with GO, you don’t need to do so in case, if you need following cases to get executed, you need to mention that explicitly. It is something small but I think a wise and most thoughtful decision.
Output(x=0):
Value of x = 0
Output(x=1):
Value of x = 1
Output(x>2):
Default
Example of fallthrough:
func main() { x := 1 switch x { case 0: fmt.Println("Value of x =", 0) case 1: fmt.Println("Value of x =", 1) fallthrough case 2: fmt.Println("Value of x =", 2) default: fmt.Println("Default") } }
http://play.golang.org/p/hwd7nQS4vD
Here we have added fallthrough at the end of case 1, so now when value of x = 2, we will get following output
Value of x = 1
Value of x = 2
Point to note here is that fallthrough made case 2 to execute irrespective of whether case matches. But since case 2 does not have fallthrough the implicit break, breaks the flow and default is not executed.
defer
This keyword is used to defer execution at the end of function. This statement can appear anywhere in the function, but will be executed at the end of the function. Let us look at the example below to understand more.
func main() { defer completed() fmt.Println("Start execution") validate() } func completed() { fmt.Println("Successfully completed execution") } func validate() { fmt.Println("Validation successful") }
http://play.golang.org/p/DVh9Xqg0sb
In above example, we have 2 functions completed and validate. On first line of main function we call defer to completed function. This will defer the call to the function completed until the end of the main function.
Output:
Start execution
Validation successful
Successfully completed execution
Conclusion
We got introduced to various control flow statements like for, if-else, switch etc. GO does not have a lot of control statements, but they have made changes to use the existing ones to handle most of the use cases. In the next post, we will look at more types like struct, array, slices etc.