Vee's Golang Notes

Program Structure & Looping Constructs

21 Sep 2025

Program Structure & Looping Constructs

Structuring Programs in Go

Go encourages a modular approach to building programs.
Functions provide process abstraction, making code easier to understand, test, and maintain.

  • A Go program consists of one or more packages.
  • Execution starts in the main package, specifically in the main() function.
  • Functions can be user-defined or come from the standard library.

Functions in Go

  • Functions must be declared (with their signature) before use.
  • They cannot be nested inside other functions.
  • They can be defined across multiple files as long as they belong to the same package.

Example:

package main
 
import (
    "fmt"
)
 
func getNum() int { // function definition
    var number int
    fmt.Print("Please enter a number: ")
    fmt.Scan(&number)
    return number
}
 
func main() { // program entry point
    a := getNum() // function call
    b := getNum()
    if a > b {
        fmt.Printf("%d is the largest\n", a)
    } else {
        fmt.Printf("%d is the largest\n", b)
    }
}

Function Arguments

Values are passed into functions via argument lists.

func add(a int, b int) int {
    return a + b
}
 
func main() {
    result := add(4, 5)
    fmt.Println(result) // 9
}
  • Formal parameters specify types and names of arguments.
  • Actual arguments must match in type and number when calling.

Go uses positional arguments—the order matters.


Function Declarations (Prototypes)

Unlike C++, Go does not require forward declarations or prototypes.
Functions can be defined in any order within a package, as long as they’re in the same package scope.


Multiple Return Values

Go functions can return multiple values, which is a common idiom.

func minMax(a, b int) (int, int) {
    if a > b {
        return b, a
    }
    return a, b
}
 
func main() {
    low, high := minMax(4, 9)
    fmt.Println(low, high) // 4 9
}

Variadic Functions

Functions can accept a variable number of arguments.

func sum(nums ...int) int {
    total := 0
    for _, n := range nums {
        total += n
    }
    return total
}
 
func main() {
    fmt.Println(sum(1, 2, 3, 4)) // 10
}

Passing Values

Go supports pass-by-value semantics for all arguments:

  • Primitives (int, float, bool, string) are copied.
  • Slices, maps, channels, interfaces, and functions are reference-like types; the reference is copied, but underlying data is shared.

Example: Pass by Value

func swap(a, b int) {
    a, b = b, a
}
 
func main() {
    x, y := 5, 6
    swap(x, y)
    fmt.Println(x, y) // 5 6 (unchanged)
}

Using Pointers for Mutation

To modify the caller’s variables, use pointers:

func swap(a, b *int) {
    *a, *b = *b, *a
}
 
func main() {
    x, y := 5, 6
    swap(&x, &y)
    fmt.Println(x, y) // 6 5
}

Go has no & or * operators for references like C++ references, but pointers provide similar behavior.


Scope

Scope determines visibility of variables.

  • Package-level variables are visible to all files in the same package.
  • Function-level variables are local to that function.
  • Block-level variables are local to a { ... } block.
var global int // package scope
 
func main() {
    x := 5 // function scope
    {
        y := 10 // block scope
        fmt.Println(x, y, global)
    }
    // fmt.Println(y) // ❌ not visible here
}

Control Flow: Loops

Go has only one loop keyword: for.
It can act like while, do-while, or a traditional for loop.

While-Style Loop

i := 10
for i > 0 {
    fmt.Println(i)
    i--
}

Infinite Loop

for {
    fmt.Println("running")
    break
}

For with Multiple Conditions

for a, b := 0, 0; (a < 1 || a > 10) || (b > 10 || b < 1); {
    fmt.Print("enter two numbers between 1 and 10: ")
    fmt.Scan(&a, &b)
}

Go does not have a do-while loop.
Use a for loop with break to simulate one:

var a, b int
for {
    fmt.Print("enter two numbers between 1 and 10: ")
    fmt.Scan(&a, &b)
    if (a >= 1 && a <= 10) && (b >= 1 && b <= 10) {
        break
    }
}

Basic for Loop

The classic loop has three components: initialization, condition, and post-update.

for i := 0; i < 10; i++ {
    fmt.Println(i)
}
  • Initialization: runs once before the loop starts (i := 0).
  • Condition: checked before each iteration (i < 10).
  • Post-update: executed after each iteration (i++).
  • The loop variable i is scoped inside the loop.

Any of these sections can be omitted:

for ; condition ; { ... }   // like a while loop
for { ... }                 // infinite loop

While-Style Loop

Go does not have a while keyword.
Use a for with only a condition:

i := 10
for i > 0 {
    fmt.Println(i)
    i--
}

Do-While Equivalent

Go has no direct do…while.
Simulate it with an infinite loop and a break:

for {
    fmt.Print("Enter a number (0 to quit): ")
    var n int
    fmt.Scan(&n)
    if n == 0 {
        break
    }
}

Range Loop

Use range to iterate over arrays, slices, maps, strings, or channels.

nums := []int{2, 4, 6, 8}
for i, v := range nums {
    fmt.Printf("Index %d → Value %d\n", i, v)
}
  • i is the index (or key for maps).
  • v is the value (or rune when iterating over strings).
  • Use _ to ignore an index or value:
for _, v := range nums {
    fmt.Println(v)
}

range automatically handles UTF-8 in strings:

for _, r := range "Golang" {
    fmt.Printf("%c ", r)
}

Break and Continue

  • break exits the nearest loop.
  • continue skips to the next iteration.
for i := 0; i < 10; i++ {
    if i == 3 { continue } // skip 3
    if i == 7 { break }    // stop entirely
    fmt.Println(i)
}

If Statement

Go uses a straightforward if syntax:

if x > 10 {
    fmt.Println("x is big")
} else if x == 10 {
    fmt.Println("x is exactly 10")
} else {
    fmt.Println("x is small")
}

Short Declarations in If
You can declare a variable that exists only inside the if and else blocks:

if n := len(name); n > 5 {
    fmt.Println("Long name")
} else {
    fmt.Println("Short name")
}

Ternary Operator

Go does not have ?:.
Use a regular if or write a helper function:

// Instead of a > b ? a : b
max := a
if b > a {
    max = b
}

Switch Statement

Go’s switch is more flexible than C++:

switch day {
case 0:
    fmt.Println("Monday")
case 1:
    fmt.Println("Tuesday")
case 5, 6:
    fmt.Println("Weekend")
default:
    fmt.Println("Unknown")
}
  • No need for break: cases don’t fall through by default.
  • Use fallthrough to intentionally continue:
switch x {
case 1:
    fmt.Println("one")
    fallthrough
case 2:
    fmt.Println("one or two")
}

Switch without a value
Acts like chained if statements:

switch {
case x < 0:
    fmt.Println("negative")
case x == 0:
    fmt.Println("zero")
default:
    fmt.Println("positive")
}

Infinite Loops

A loop that runs forever:

for {
    // do work
}

Combine with break or return to exit.