DEV Community

Cover image for Mastering Golang Statements: Unknown to Expert
Ayoub Ali
Ayoub Ali

Posted on

Mastering Golang Statements: Unknown to Expert

Introduction

In Go programming, The statements are the voice of your code. They serve as concise directives, written as sequences of tokens, which guide the Go interpreter or compiler in executing specific tasks or actions. Each statement is akin to a command, instructing the program on what to do next.

These statements are the building blocks of any Go program, encompassing a wide range of actions, from declaring variables and performing calculations to making pivotal decisions and handling potential errors. In essence, they encapsulate the programmer's intentions, enabling the computer to execute tasks with precision and order.

Classification of Statements In Golang

Classification Description
Declaration Statements Statements for declaring variables, constants, and custom types.
Assignment Statements Statements for assigning values to variables.
Control Flow Statements Statements for controlling program flow (if, switch, for, etc.).
Control Structures Statements for controlling function flow (return, defer, panic, recover).
Function Calls Statements that invoke functions or methods.
Defer Statements Statements that defer function execution.
Label Statements Statements used with "goto" for code jumping.
Expression Statements Statements with expressions that have side effects.
Empty Statements Statements that do nothing, often a single semicolon.
Incidental Statements Statements resulting from expressions (e.g., method calls).

1. Declaration Statements:

  • var: Used to declare variables.
  • const: Used to declare constants.
  • type: Used to define custom data types.
package main

import "fmt"

func main() {
    // Declaration and initialization of a variable
    var age int // Declare an integer variable named "age"
    age = 30    // Initialize "age" with the value 30

    // Declaration and initialization of multiple variables
    var (
        name    string  // Declare a string variable named "name"
        height  float64 // Declare a float64 variable named "height"
        married bool    // Declare a boolean variable named "married"
    )

    name = "Alice"       // Initialize "name" with the string "Alice"
    height = 165.5       // Initialize "height" with the float 165.5
    married = true       // Initialize "married" with the boolean value true

    // Short variable declaration with initialization
    country := "USA"     // Declare and initialize "country" as a string
    temperature := 25.5  // Declare and initialize "temperature" as a float64

    // Output the values of the declared variables
    fmt.Println("Name:", name)
    fmt.Println("Age:", age)
    fmt.Println("Height:", height)
    fmt.Println("Married:", married)
    fmt.Println("Country:", country)
    fmt.Println("Temperature:", temperature)
}
Enter fullscreen mode Exit fullscreen mode

2. Assignment Statements:

  • =: Used to assign values to variables.
  • +=, -=, *=, /=, ...: Used for compound assignments.
package main

import "fmt"

func main() {
    // Declare variables
    var x, y int

    // Assignment statements
    x = 10           // Assign the value 10 to variable x
    y = x + 5        // Assign the result of x + 5 to variable y

    // Short assignment statement
    z := 7           // Declare and assign the value 7 to variable z

    // Multiple assignments
    a, b := 3, 4     // Declare and assign 3 to a and 4 to b simultaneously

    // Swapping values using multiple assignments
    a, b = b, a      // Swap the values of a and b

    // Output the values of variables
    fmt.Println("x:", x)
    fmt.Println("y:", y)
    fmt.Println("z:", z)
    fmt.Println("a:", a)
    fmt.Println("b:", b)
}
Enter fullscreen mode Exit fullscreen mode

3. Control Flow Statements:

  • if: Used for conditional execution of code.
  • else: Used in conjunction with "if" for alternative execution.
  • switch: Used for multi-way conditionals.
  • case: Used within a "switch" statement to specify cases.
  • default: Used in "switch" to specify the default case.
  • for: Used for loops.
  • break: Used to exit a loop or switch.
  • continue: Used to skip the rest of the current loop iteration.
  • goto: Used for unconditional jumps to labeled statements (rarely used).
package main

import "fmt"

func main() {
    // if statement
    age := 20
    if age >= 18 {
        fmt.Println("You are an adult.")
    } else {
        fmt.Println("You are not yet an adult.")
    }

    // switch statement
    dayOfWeek := "Monday"
    switch dayOfWeek {
    case "Monday":
        fmt.Println("It's the start of the workweek.")
    case "Friday":
        fmt.Println("It's almost the weekend!")
    default:
        fmt.Println("It's an ordinary day.")
    }

    // for loop
    fmt.Println("Counting from 1 to 5:")
    for i := 1; i <= 5; i++ {
        fmt.Println(i)
    }

    // break and continue statements
    fmt.Println("Counting from 1 to 10, skipping even numbers:")
    for j := 1; j <= 10; j++ {
        if j%2 == 0 {
            continue // Skip even numbers
        }
        fmt.Println(j)
        if j == 5 {
            break // Exit the loop when j is 5
        }
    }

    // goto statement (rarely used)
    counter := 0
loop:
    if counter < 5 {
        fmt.Println("In the loop.")
        counter++
        goto loop
    }
    fmt.Println("Exited the loop.")
}
Enter fullscreen mode Exit fullscreen mode

4. Control Structures:

  • return: Used to return a value from a function.
  • defer: Used to schedule a function call to be executed at the end of the current function.
  • panic: Used to trigger a runtime panic (exception) with a value.
  • recover: Used to handle panics by regaining control over the program.
package main

import "fmt"

func main() {
    // Call the divide function with arguments 10 and 0
    result := divide(10, 0)

    // Print the result (which will be 0 due to the panic and recovery)
    fmt.Println("Result:", result)
}

// divide is a function that takes two integers and returns an integer result.
func divide(a, b int) (result int) {
    // Defer a function to recover from panics and handle them gracefully
    defer func() {
        if r := recover(); r != nil {
            // Print a message indicating a panic was recovered
            fmt.Println("Recovered from panic:", r)
            // Set the result to 0 to handle the error gracefully
            result = 0
        }
    }()

    // Check if b is equal to zero, and if so, panic with a message
    if b == 0 {
        panic("Division by zero")
    }

    // Calculate the result of the division
    return a / b
}
Enter fullscreen mode Exit fullscreen mode

5. Function Calls:

  • Statements that invoke functions or methods.
package main

import "fmt"

// Function definition
func greet(name string) {
    fmt.Println("Hello, " + name + "!")
}

// Function with multiple parameters and a return value
func add(a, b int) int {
    return a + b
}

func main() {
    // Function call with an argument
    greet("Alice")

    // Function call with multiple arguments and capturing the result
    sum := add(5, 3)

    // Print the result of the function call
    fmt.Println("Sum:", sum)

    // Function call without capturing the result
    sayHello("Bob")
}

// Function with no return value
func sayHello(name string) {
    fmt.Println("Hey there, " + name + "!")
}

// Anonymous Function

// execute when used
sum := func(a, b int) int {
    return a + b
}

// will execute immediately
func() {
    fmt.Println("Hello, anonymous function!") 
}()

fmt.Println("Sum is : ", sum(3, 4))

// Function closures

func adder() func(int) int {
    total := 0  // outer function's variable
    return func(x int) int {  // can modify total's value across function calls
        total += x  // references total and modify it
        return total
    }
}


// use this function as below
a := adder()
fmt.Println(a(1)) // 0 + 1 = 1
fmt.Println(a(2)) // 1 + 2 = 3
fmt.Println(a(3)) // 3 + 3 = 6

// Blank identifier

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

// Variadic functions

func concatStrings(separator string, words ...string) string {
    var result string
    for i, s := range words {
        if i > 0 {
            result += separator
        }
        result += s
    }
    return result
}

result := concatStrings(" ", "hello", "world", "!")
fmt.Println(result) // Output: "hello world !"

Enter fullscreen mode Exit fullscreen mode

6. Defer Statements:

  • Statements that defer the execution of a function until the surrounding function returns.
package main

import "fmt"

func main() {
    defer fmt.Println("This will be executed last")
    fmt.Println("This will be executed first")

    for i := 1; i <= 5; i++ {
        defer fmt.Printf("Deferred %d\n", i)
    }

    fmt.Println("These lines will be executed before deferred statements")
}
Enter fullscreen mode Exit fullscreen mode

7. Label Statements:

  • Identifier: Labels are used with "goto" statements for jumps to specific points in the code.
package main

import "fmt"

func main() {
    // Define a label
Start:
    fmt.Println("This is the start of the program.")

    // Outer loop
    for i := 0; i < 3; i++ {
        fmt.Printf("Outer loop iteration %d\n", i)

        // Inner loop
        for j := 0; j < 3; j++ {
            fmt.Printf("  Inner loop iteration %d\n", j)

            // Check a condition
            if i == 1 && j == 1 {
                fmt.Println("    Breaking out of loops.")
                // Jump to the defined label
                goto End
            }
        }
    }

    // This code will not be executed because of the 'goto'
    fmt.Println("This will not be printed.")

End:
    fmt.Println("This is the end of the program.")
}
Enter fullscreen mode Exit fullscreen mode

8. Expression Statements:

  • Statements that consist of expressions (e.g., function calls or calculations) that do not assign values or control program flow but have side effects.
package main

import (
    "fmt"
    "math/rand"
    "time"
)

func main() {
    // Initialize the random number generator with the current time
    rand.Seed(time.Now().UnixNano())

    // Generate and print a random number
    randomNum := rand.Intn(100) // This is an expression statement with a side effect (printing)
    fmt.Println("Random number:", randomNum)

    // Open a file for writing (simulated, not an actual file operation)
    file := OpenFile("example.txt") // This is an expression statement with a side effect (file interaction)
    defer CloseFile(file)          // This is another expression statement with a side effect (deferring a close operation)

    // Perform some calculations without assigning the result
    _ = 3 * 7 // This is an expression statement with a calculation but no assignment
}

func OpenFile(filename string) *File {
    fmt.Println("Opening file:", filename)
    // Simulated file open operation; returns a file object
    return &File{}
}

func CloseFile(file *File) {
    fmt.Println("Closing file")
    // Simulated file close operation
}

type File struct {
    // Simulated file representation
}
Enter fullscreen mode Exit fullscreen mode

These expression statements with side effects are common in Go when dealing with I/O, logging, and other operations that don't directly assign values or control program flow but have important side effects.

9. Empty Statements:

  • A single semicolon (";") used as a statement that does nothing. Rarely used and typically used to satisfy syntax requirements.
package main

import "fmt"

func main() {
    for i := 0; i < 5; i++ {
        fmt.Println(i)  // This is a regular statement
        ;               // This is an empty statement
    }
}
Enter fullscreen mode Exit fullscreen mode

Empty statements are rarely used in practice because they can make the code less readable and are generally considered unnecessary. However, there may be situations where they are used as placeholders or for specific code formatting requirements.

10. Incidental Statements:

  • Statements that occur as a result of expressions, such as array/slice indexing, method calls, or function calls.
package main

import "fmt"

func main() {
    // Define a slice of integers
    numbers := []int{1, 2, 3, 4, 5}

    // Array/slice indexing expression used in a statement
    firstNumber := numbers[0]
    fmt.Println("First Number:", firstNumber)

    // Method call expression with a side effect (printing)
    greet("Alice")

    // Function call expression with a result assigned to a variable
    sum := calculateSum(numbers)
    fmt.Println("Sum of numbers:", sum)
}

// Function that greets a person
func greet(name string) {
    fmt.Println("Hello,", name)
}

// Function that calculates the sum of integers in a slice
func calculateSum(nums []int) int {
    sum := 0
    for _, num := range nums {
        sum += num
    }
    return sum
}
Enter fullscreen mode Exit fullscreen mode

These are statements that might appear in code but don't serve a specific purpose or have unintended side effects. It's important to note that such statements should generally be avoided in real code, as they can lead to confusion and maintenance issues.

Other statements

1. Type Assertions

A type assertion is used to extract the underlying value of an interface type when you know the actual concrete type of that value. It allows you to access the concrete value and perform operations on it. Type assertions are most commonly used when dealing with interface types, like the interface{} empty interface or user-defined interfaces.

package main

import "fmt"

func main() {
    var i interface{} = 42

    // Type assertion to extract the underlying int value
    v, ok := i.(int)
    if ok {
        fmt.Printf("The value is an integer: %d\n", v)
    } else {
        fmt.Println("The value is not an integer.")
    }

    // Type assertion to extract a type that doesn't match
    f, ok := i.(float64)
    if ok {
        fmt.Printf("The value is a float64: %f\n", f)
    } else {
        fmt.Println("The value is not a float64.")
    }
}
Enter fullscreen mode Exit fullscreen mode

2. Select Statement

The select statement is used for communication and synchronization between go-routines (concurrent threads of execution). It allows you to choose one of several communication operations that are ready to proceed. The select statement operates on channels and is often used to coordinate the flow of data between go-routines.

package main

import (
    "fmt"
    "time"
)

func main() {
    ch1 := make(chan string)
    ch2 := make(chan string)

    go func() {
        time.Sleep(2 * time.Second)
        ch1 <- "Hello from goroutine 1"
    }()

    go func() {
        time.Sleep(1 * time.Second)
        ch2 <- "Hello from goroutine 2"
    }()

    select {
    case msg1 := <-ch1:
        fmt.Println(msg1)
    case msg2 := <-ch2:
        fmt.Println(msg2)
    }
}
Enter fullscreen mode Exit fullscreen mode

About Me

I'm a Software Engineer. I Write Backend Stuff and Mostly Love to Write and Implement Algorithms & Tools and AI a Stuff and Meanwhile in my free time I Research about Security and Malware Stuff That Help to Write better Code adn find any Security Loopholes. I am Expert in Go & Dart & in TypeScript.

GitHub Profile

Visit my Leetcode Repo Where I implemented more than 200+ Solution in Go & Dart

Leetcode

Top comments (0)