Configuration

Night mode

Flow Control

A$AP Learn Go (GoLang) 🚀 Course

Engineers From These Top Companies and Universities Trust EXLskills

1M+ Professionals | 100+ Institutions

This is the EXLskills free and open-source A$AP Learn GoLang Course! It's a highly-accelerated open course that's best-suited for people with a bit of background in software engineering to quickly pick up Go, learn the essential best practices, and hit the ground running!
After this course, you'll be able to build basic Go applications in addition to lightweight webservers, highly-concurrent programs, and reusable libraries in Go that you can share with other developers!
For further practice, we recommend checking out our Go Guided Projects that will give you access to a professional Go developer, detailed documentation, and real-world tasks that you can work on to go from the basics of Go, into building production apps.

Is this course FREE?

Yes, this a 100% free course that you can contribute to on GitHub here!

Have more questions?

Essentials of Go

Flow Control

Building Logic and Controlling Execution Flow in Go

Flow control in Go will feel very familiar to many developers who already have an experience with a language that has a more or less C-style syntax. There are some neat syntactical benefits that Go offers, which allows to have cleaner and often terser code.

Available Statements

if, if/else, if/else if/else are the most commonly-used logical statements

switch (with cases and a default) is a common way to manage flow based on the value of a single variable

for is the only way to loop in Go (we don't have while loops in Go)

To iterate over a slice/array/map we can use the range keyword (explained in the code below)

goto is available in Go, however, it is infrequently used (although there are definitely some use cases for it, where it helps to simplify code)

Flow Control in Practice

package main
import (
"fmt"
)
func main() {
showIfStatements()
showSwitchStatements()
showForStatements()
fmt.Println("Got", showGotoStatements(), "from showGotoStatements()")
}
func showIfStatements() {
t, f := true, false
// Note that `if` statements don't have parentheses, only braces around the code block
if true {
fmt.Println("True is definitely true!")
}
if t == f {
fmt.Println("Nope!")
} else if t != f {
fmt.Println("Makes sense")
} else if t == !f {
fmt.Println("Also true, but we didn't get this far")
} else {
fmt.Println("Nope ...")
}
}
func showSwitchStatements() {
// Sometimes it's best to use switch in order to avoid long chains of if/else if/else's
myNum := 21
switch myNum {
case 1,2,42:
// This would get called if myNum == 1 OR 2 OR 42
fmt.Println("Cool. myNum is either 1, 2, or 42")
// ⚠️ Remember that in Go, cases DO NOT fall through by default!
break // So this is actually redundant here, but just to show that we _can_ manually break as well
case 3:
// This is a no-op case, i.e., if we _want_ to do nothing when myNum == 3
case 5:
// ⭐ If you want to fall through, you can (the fallthrough must be the last line of that case)
fallthrough
default:
// Optionally, we can have a default case that gets applied either via an explicit fallthrough or when no case matches
}
}
func showForStatements() {
// Setup some dummy data (these will be explained in "Core Datatypes" so don't worry if they are unfamiliar right now)
colorsMap := map[string]string{
"AliceBlue": "#F0F8FF",
"AntiqueWhite": "#FAEBD7",
"Aqua": "#00FFFF",
"Aquamarine": "#7FFFD4",
// NB: Go requires this trailing comma on the last element when initializing values over multiple lines
"Azure": "#F0FFFF",
}
colorsSlice := make([]string, 0, len(colorsMap))
// Here, we use the `range` keyword to have Go iterate over the `colorsMap` and set `name` to the "key" in
// the map, while setting `hexStrValue` to the value for that particular key in the map.
for name, hexStrValue := range colorsMap {
colorsSlice = append(colorsSlice, fmt.Sprintf("%s:%s", name, hexStrValue))
}
// You can also use range on slices (as below) -- and even `chan`s (explained further in concurrency)
// If you don't need the key or index, you can use the blank `_` to ignore it
for _, colorPairValue := range colorsSlice {
fmt.Println(colorPairValue)
}
// NB: Like `if` statements, `for` loops do not use parenthesis -- just braces around the inner block
// Iteration in Go is essentially the same as in Java/C/C++
for x := 0; x < 3; x++ {
// Remember that variables declared in `for` and `if` statements or blocks are scoped to that block
fmt.Println("iteration", x)
}
// Since we don't have while loops, we can also use this form of `for` to create infinite loops
for {
// `break` allows us to leave the for loop
break
// `continue` allows us to move on to the next iteration in the loop (leaving the current iteration)
continue // This wouldn't be reached in this case, as we used `break` to leave above
}
}
func showGotoStatements() int {
// This example isn't particularly useful (for clarify and brevity)
fmt.Println("Let's see how goto works...")
i := 0
if i == 0 {
goto namedBlock
} else {
goto otherBlock
}
// That's it, the goto will make one of these blocks finsh and return from the function
passBack:
return i
namedBlock:
fmt.Println("Hey, I was invoked via a goto statement!")
i++
goto passBack
otherBlock:
fmt.Println("Hey, I'm another block. Did I get invoked??")
i--
goto passBack
}

Keep it Idiomatic!

In Go, we generally:

Avoid the use of the _ blank identifier unless we have a significant reason to do so, or are calling a function or using range in a for-loop where we have multiple assignment, but we don't need some of the returned values. By the way, you shouldn't just throw your errors from function calls into _, because if someone is sending you back a potential error value, you should check it!!!

Using the := is convenient and idiomatic, however, remember that you can sometimes end up with multiple copies of a variable if, for instance, you have an err outside of a for loop, and then you have another err that you create via the := operator, you will actually be using a completely different variable on each iteration of your loop! Something to keep in mind!

It's not that common to pass functions around as arguments in Go, primarily since we prefer to use goroutines for concurrency, rather than 'callbacks' (like JS does, for instance), however it's still used for things like walking a file tree or applying a specific transformation to some data that another function is analyzing