Loading...
Loading...

Go Control Structures Tutorial

Control structures in Go determine the flow of program execution. Unlike many languages, Go keeps its control structures minimal and explicit, with only one looping construct (for) but flexible conditional branching.

1. If Statements

The if statement evaluates a condition and executes a block of code if the condition is true. Go's if has several unique characteristics.

if x > 10 {
    fmt.Println("x is large")
} else if x > 5 {
    fmt.Println("x is medium")
} else {
    fmt.Println("x is small")
}

Key Features:

  • No parentheses around conditions (unlike C-family languages)
  • Braces are always required, even for single-line blocks
  • Can include an optional initialization statement before the condition

Initialization Statement:

if err := process(); err != nil {
    fmt.Println("Error:", err)
}

The initialization statement (before the semicolon) limits the variable's scope to the if-else block, a clean way to handle temporary variables.

If Statement Quiz

What happens to variables declared in the if initialization?

  • They become global variables
  • They're only available in the if-else blocks
  • They must be manually freed

2. For Loops

Go has only one looping construct - the for loop - that serves three purposes: traditional loops, while loops, and infinite loops.

Traditional For Loop:

for i := 0; i < 5; i++ {
    fmt.Println(i)
}

While-Style Loop:

count := 0
for count < 5 {
    fmt.Println(count)
    count++
}

Infinite Loop:

for {
    fmt.Println("Looping forever")
    break // Needed to exit
}

Range-Based Loop:

nums := []int{2, 4, 6}
for index, value := range nums {
    fmt.Println(index, value)
}

Key Notes:

  • All four forms use the for keyword
  • No parentheses around conditions
  • break exits the loop, continue skips to next iteration
  • Range loops work with arrays, slices, strings, maps, and channels

For Loop Quiz

How do you write a while loop in Go?

  • while condition { }
  • for condition { }
  • loop condition { }

3. Switch Statements

Go's switch is more flexible than C-style switches, with several important differences.

Basic Switch:

switch day {
case "Mon":
    fmt.Println("Monday")
case "Tue":
    fmt.Println("Tuesday")
default:
    fmt.Println("Other day")
}

Switch with Initializer:

switch time.Now().Weekday() {
case time.Saturday, time.Sunday:
    fmt.Println("Weekend")
default:
    fmt.Println("Weekday")
}

Type Switch:

switch v := x.(type) {
case int:
    fmt.Println("Integer:", v)
case string:
    fmt.Println("String:", v)
default:
    fmt.Println("Unknown type")
}

Key Differences from C/Java:

  • No fallthrough between cases (unless explicitly using fallthrough)
  • Cases don't need to be constants
  • Can switch on any type, not just integers
  • Default case is optional

Switch Quiz

What happens by default after a case matches?

  • Execution falls through to next case
  • Only that case's code runs
  • All remaining cases execute

4. Defer Statement

The defer statement postpones execution of a function until the surrounding function returns, making it ideal for cleanup tasks.

func readFile() {
    file, _ := os.Open("data.txt")
    defer file.Close()
    
    // File operations here
    // file.Close() will be called automatically
}

Key Characteristics:

  • Arguments to deferred functions are evaluated immediately
  • Defers execute in LIFO (last-in-first-out) order
  • Commonly used for resource cleanup (files, locks, connections)
  • Works with named return values (can modify return values)

Multiple Defers Example:

func example() {
    defer fmt.Println("First defer")
    defer fmt.Println("Second defer")
    fmt.Println("Function body")
    // Output:
    // Function body
    // Second defer
    // First defer
}

Defer Quiz

When are deferred functions executed?

  • Immediately after declaration
  • When the surrounding function returns
  • At program exit

5. Panic and Recover

Go uses panic and recover for exceptional error handling, though they're rarely needed in normal operation.

Panic:

func riskyOperation() {
    panic("Something went terribly wrong")
}

Recover:

func safeCall() {
    defer func() {
        if r := recover(); r != nil {
            fmt.Println("Recovered from:", r)
        }
    }()
    riskyOperation()
}

Key Points:

  • panic stops normal execution and begins panicking
  • recover can stop the panic and return the panic value
  • Only useful inside deferred functions
  • Not for normal error handling - prefer returning errors

Panic Quiz

Where must recover be called to catch a panic?

  • At the start of the function
  • Inside a deferred function
  • Right after the panic call

6. Select Statement

The select statement lets a goroutine wait on multiple communication operations, primarily used with channels.

select {
case msg := <-channel1:
    fmt.Println("Received", msg)
case channel2 <- "hello":
    fmt.Println("Sent hello")
case <-time.After(1 * time.Second):
    fmt.Println("Timeout")
default:
    fmt.Println("No activity")
}

Key Features:

  • Blocks until one of the cases can run
  • If multiple cases are ready, one is chosen at random
  • The default case runs immediately if no other case is ready
  • Often used with timeouts using time.After

Select Quiz

What happens if multiple select cases are ready?

  • They execute in order
  • One is chosen randomly
  • All execute simultaneously

7. Common Patterns

Go developers use several idiomatic control flow patterns for common scenarios.

Error Handling Pattern:

if err := doSomething(); err != nil {
    // Handle error
    return err
}
// Continue with success case

Worker Pool Pattern:

for task := range tasks {
    go func(t Task) {
        // Process task
    }(task)
}

Timeout Pattern:

select {
case result := <-operationChan:
    // Use result
case <-time.After(2 * time.Second):
    // Handle timeout
}

Key Idioms:

  • Early returns for error handling
  • Using channels for synchronization
  • Context package for cancellation
  • Worker pools for controlled concurrency

Patterns Quiz

What's the preferred error handling style in Go?

  • Try/catch blocks
  • Checking returned error values
  • Global error handlers
0 Interaction
0 Views
Views
0 Likes
×
×
×
🍪 CookieConsent@Ptutorials:~

Welcome to Ptutorials

$ Allow cookies on this site ? (y/n)

top-home