🐹 Go

الدوال والتكرار في Go 1.21: دليل مفصل

Functions and Recursion in Go

Introduction: Why Do We Need Functions?

Imagine you are learning to bake pies. Every time you need to bake a pie, you don't reinvent the entire process: you take the dough, shape it, put it in the oven. You simply use a ready-made recipe.

In programming, a function is the same kind of recipe. It is a block of code that performs one specific task. You can use it again and again without rewriting the code each time.

When a function calls itself, it is called recursion. It's like a Russian nesting doll (matryoshka): inside a large doll there is a smaller one, inside it an even smaller one, and so on down to the smallest one.

Basic Function Syntax in Go

In Go, a function starts with the keyword func, followed by its name, parameters (input data) in parentheses, and the return type after the parentheses.

// Simple function without parameters
func sayHello() {
    fmt.Println("Hello, world!")
}

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

// Function with two return values
func divide(a, b int) (int, int) {
    return a / b, a % b // return quotient and remainder
}

Example 1: Family Budget (Sum of Two Numbers)

Let's write a program that takes two numbers (incomes) and prints their sum.

package main

import "fmt"

// Function to calculate the sum of incomes
func sumIncome(a float64, b float64) float64 {
    return a + b
}

func main() {
    var income1, income2 float64

    fmt.Print("Enter first income: ")
    fmt.Scan(&income1)

    fmt.Print("Enter second income: ")
    fmt.Scan(&income2)

    total := sumIncome(income1, income2)
    fmt.Printf("Total income: %.2f\n", total)
}

How it works:

  • We declared the function sumIncome, which takes two numbers and returns their sum.
  • In main, we read the numbers from the keyboard, call the function, and print the result.

Example 2: Temperature Comparison

The function takes two temperatures and returns the larger one.

package main

import "fmt"

// Function to find the maximum
func maxTemperature(t1 float64, t2 float64) float64 {
    if t1 > t2 {
        return t1
    }
    return t2
}

func main() {
    var temp1, temp2 float64

    fmt.Print("Enter first temperature: ")
    fmt.Scan(&temp1)

    fmt.Print("Enter second temperature: ")
    fmt.Scan(&temp2)

    result := maxTemperature(temp1, temp2)
    fmt.Printf("Higher temperature: %.1f\n", result)
}

Example 3: Even Number Check (Returning bool)

The function returns true if the number is even, and false if it is odd.

package main

import "fmt"

// Function to check evenness
func isEven(n int) bool {
    return n%2 == 0
}

func main() {
    var boxes int

    fmt.Print("How many boxes were produced? ")
    fmt.Scan(&boxes)

    if isEven(boxes) {
        fmt.Println("The number is even — can be packed in pairs!")
    } else {
        fmt.Println("The number is odd — one box will be left without a pair.")
    }
}

Recursion: When a Function Calls Itself

Recursion is convenient for tasks that can be broken down into the same but smaller sub-tasks.

Important rule: recursion must always have a base case (exit condition), otherwise the program will loop infinitely.

Example 4: String Reversal (Recursion)

Let's reverse a string using recursion.

package main

import "fmt"

// Recursive function to reverse a string
func reverseString(s string) string {
    // Base case: if the string is empty or has one character
    if len(s) <= 1 {
        return s
    }
    // Take the last character + recursively reverse the rest
    return string(s[len(s)-1]) + reverseString(s[:len(s)-1])
}

func main() {
    var text string

    fmt.Print("Enter a string: ")
    fmt.Scan(&text)

    result := reverseString(text)
    fmt.Println("Result:", result)
}

How it works:

  • If the string has one character — return it (base case).
  • Otherwise, take the last character and prepend it to the reversed string without the last character.

Example 5: Finding the Minimum Element in a List (Recursion)

package main

import "fmt"

// Recursive function to find the minimum
func findMin(arr []int, n int) int {
    // Base case: if the array has one element
    if n == 1 {
        return arr[0]
    }
    // Find the minimum in the smaller part of the array
    min := findMin(arr, n-1)
    // Compare with the last element
    if arr[n-1] < min {
        return arr[n-1]
    }
    return min
}

func main() {
    // Example data: daily temperatures
    temperatures := []int{-5, 3, -8, 12, 0, 7, -2}

    minTemp := findMin(temperatures, len(temperatures))
    fmt.Printf("Lowest temperature: %d°C\n", minTemp)
}

Common Beginner Mistakes

  1. Forgetting to specify the return type — if a function returns something, you must write the type after the parentheses.
  2. Confusing parameters and arguments — parameters are the variables in the function definition; arguments are the specific values when calling the function.
  3. Infinite recursion — forgetting to write a base case. The program will run until memory runs out.
  4. Not using return in all branches — if a function returns a value, return must be present in all cases (both in if and else).
  5. Trying to modify parameters inside the function — in Go, parameters are passed by value (copied). Modifying a parameter does not affect the original variable.

Final Example: