Chapter 2: Control Structures

Conditional Statements (if, else, switch)

In Go, conditional statements (if, else, switch) are essential for controlling the flow of execution based on certain conditions. Here’s a detailed explanation without using a list:

Conditional Statements in Go

if Statement:

The if statement evaluates a boolean condition and executes a block of code if the condition is true.

go

package main

import "fmt"

func main() {
age := 18

if age >= 18 {
fmt.Println("You are an adult.")
}

// if-else statement
if age >= 18 {
fmt.Println("You are eligible to vote.")
} else {
fmt.Println("You are not eligible to vote.")
}

// if-else-if ladder
if age < 12 {
fmt.Println("You are a child.")
} else if age < 18 {
fmt.Println("You are a teenager.")
} else {
fmt.Println("You are an adult.")
}
}

switch Statement:

The switch statement evaluates an expression and compares it against multiple possible cases. It executes the case whose value matches the expression.

go

package main

import "fmt"

func main() {
day := "Monday"

switch day {
case "Monday":
fmt.Println("Today is Monday.")
case "Tuesday":
fmt.Println("Today is Tuesday.")
case "Wednesday", "Thursday":
fmt.Println("Today is midweek.")
default:
fmt.Println("It's the weekend.")
}

// switch with no expression
switch {
case day == "Monday":
fmt.Println("Today is Monday.")
case day == "Tuesday":
fmt.Println("Today is Tuesday.")
default:
fmt.Println("Today is neither Monday nor Tuesday.")
}
}

Key Points:

  • Go’s if statements are similar to those in other languages, supporting if, else, and else if.
  • switch statements in Go are more flexible than in many other languages, allowing multiple values in a case and expressions without a specific value.
  • Both if and switch can be used to control program flow based on different conditions, making code more readable and manageable.

Understanding these conditional statements is crucial for writing clear and efficient Go programs. They allow developers to control the flow of execution based on specific conditions, enhancing the flexibility and logic of their applications.

Loops in Go

for Loop:

The for loop in Go is used to iterate over a range of values or to execute a block of code repeatedly until a condition is met.

Example 1: Basic for Loop

go

package main

import "fmt"

func main() {
// Basic for loop
for i := 1; i <= 5; i++ {
fmt.Println(i)
}
}

Example 2: Loop with Multiple Variables

go

package main

import "fmt"

func main() {
// Loop with multiple variables
for i, j := 0, 5; i < j; i, j = i+1, j-1 {
fmt.Println(i, j)
}
}

Example 3: Infinite Loop

go

package main

import "fmt"

func main() {
// Infinite loop
sum := 0
for {
sum++
if sum > 10 {
break
}
}
fmt.Println("Sum:", sum)
}

Example 4: Looping Over Array/Slice

go

package main

import "fmt"

func main() {
// Looping over an array
numbers := []int{1, 2, 3, 4, 5}
for index := 0; index < len(numbers); index++ {
fmt.Println(numbers[index])
}
}

Example 5: Using continue to Skip Iteration

go

package main

import "fmt"

func main() {
// Using continue to skip iteration
for i := 1; i <= 5; i++ {
if i%2 == 0 {
continue // Skip even numbers
}
fmt.Println(i)
}
}

range Loop:

The range keyword in Go is used to iterate over elements in data structures like arrays, slices, maps, or strings.

Example 1: Looping Over Array/Slice

go

package main

import "fmt"

func main() {
// Looping over an array/slice
numbers := []int{1, 2, 3, 4, 5}
for index, value := range numbers {
fmt.Printf("Index: %d, Value: %d\n", index, value)
}
}

Example 2: Looping Over Map

go

package main

import "fmt"

func main() {
// Looping over a map
ages := map[string]int{
"Alice": 30,
"Bob": 25,
"Charlie": 35,
}
for name, age := range ages {
fmt.Printf("%s is %d years old\n", name, age)
}
}

Example 3: Looping Over String

go

package main

import "fmt"

func main() {
// Looping over a string
message := "Hello, World!"
for index, char := range message {
fmt.Printf("Character at index %d is %c\n", index, char)
}
}

Example 4: Ignoring Index Using _

go

package main

import "fmt"

func main() {
// Ignoring index using _
numbers := []int{1, 2, 3, 4, 5}
for _, value := range numbers {
fmt.Println(value)
}
}

Example 5: Looping Over Channels

go

package main

import (
"fmt"
"time"
)

func main() {
// Looping over channels
dataChannel := make(chan int)

go func() {
defer close(dataChannel)
for i := 1; i <= 5; i++ {
dataChannel <- i
time.Sleep(time.Second)
}
}()

for number := range dataChannel {
fmt.Println("Received:", number)
}
}

Key Points:

  • The for loop in Go supports basic iterations, infinite loops, multiple variables, and looping over collections.
  • The range keyword simplifies iterating over arrays, slices, maps, strings, and channels in Go.
  • Understanding these loop constructs is fundamental for writing efficient and clear Go programs, enabling developers to handle various scenarios from basic iterations to complex data structure traversals.

Error Handling in Go

Error handling in Go is managed through the use of error values. Functions that may encounter errors typically return an error as one of their return values. Here are examples demonstrating error handling in Go:

go

package main

import (
"fmt"
"os"
)

func main() {
file, err := os.Open("test.txt")
if err != nil {
fmt.Println("Error:", err)
return
}
defer file.Close() // Ensure the file is closed at the end

// Read from the file
data := make([]byte, 100)
count, err := file.Read(data)
if err != nil {
fmt.Println("Error reading file:", err)
return
}
fmt.Printf("Read %d bytes: %s\n", count, data[:count])
}
  • Explanation:
    • The os.Open function opens a file named test.txt. If an error occurs (e.g., file not found), it returns an error which is stored in err.
    • The if err != nil statement checks if err is not nil, indicating an error occurred during file opening.
    • Inside the if block, we handle the error by printing a message and returning from the function.
    • defer file.Close() ensures that the file is closed at the end of the function execution, regardless of whether an error occurred or not.
    • After handling errors, we proceed to read from the file using file.Read.

Defer in Go

The defer statement in Go is used to schedule a function call to be executed immediately before the enclosing function returns. It is commonly used for tasks like closing files, unlocking mutexes, and releasing resources. Here’s an example demonstrating the use of defer:

go

package main

import "fmt"

func main() {
fmt.Println("Start")

defer fmt.Println("Deferred statement executed")

fmt.Println("End")
}
  • Explanation:
    • In this example, fmt.Println("Deferred statement executed") is deferred until after main() finishes execution.
    • Even though defer is placed before fmt.Println("End"), it gets executed last because it is deferred until after all the surrounding function’s statements have been executed.

Key Points:

  • Error handling in Go involves returning error values from functions and checking them explicitly with if err != nil.
  • The defer statement postpones the execution of a function until the surrounding function returns, ensuring cleanup tasks are performed, regardless of how the function exits (e.g., through normal execution or due to an error).
  • Proper error handling and defer usage contribute to more robust and reliable Go programs, ensuring resources are managed effectively and errors are handled gracefully.

Comments

Leave a Reply

Your email address will not be published. Required fields are marked *