Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.syntblaze.com/llms.txt

Use this file to discover all available pages before exploring further.

A function in Go is a statically typed, named or anonymous block of statements that executes a specific operation. Go functions are first-class citizens, meaning they can be assigned to variables, passed as arguments to other functions, and returned as values.

Syntax

The declaration begins with the func keyword, followed by the identifier, a parameter list, an optional return type list, and the function body enclosed in braces.
func process(input string, count int) (string, bool) {
    // execution block
    return input, true
}

Parameters

Go uses a postfix type notation where the parameter name precedes its type.
  • Type Grouping: Consecutive parameters sharing the same type can omit the type signature until the final parameter in the group.
func add(x, y, z int) int { 
    return x + y + z 
}
  • Pass-by-Value: All arguments in Go are passed by value. A copy of the argument is allocated in the function’s stack frame. To mutate the original variable, pointers (*Type) must be passed explicitly. However, types such as slices, maps, and channels are descriptors that contain internal pointers. Passing these types by value copies the descriptor, not the underlying data, allowing the internal elements to be mutated without passing a pointer to the descriptor itself.
  • Variadic Parameters: A function can accept zero or more arguments of a specific type using the ... syntax. The variadic parameter must be the final parameter in the signature and is evaluated as a slice ([]Type) within the function body.
func sum(numbers ...int) int { 
    total := 0
    for _, n := range numbers {
        total += n
    }
    return total
}

Return Values

Go natively supports multiple return values, a mechanism heavily utilized in Go’s error-handling paradigm.
  • Multiple Returns: When returning multiple values, the return types must be enclosed in parentheses. A caller can completely ignore all return values by executing the function without assigning it to any variables. If the caller chooses to capture the return values in an assignment, Go enforces strict assignment semantics: the number of variables on the left side must exactly match the number of return values. To ignore specific unwanted return values during an assignment, the caller must assign them to the blank identifier (_).
func divide(a, b float64) (float64, error) { 
    if b == 0 {
        return 0, errors.New("division by zero")
    }
    return a / b, nil
}
  • Named Return Values: Return variables can be named directly in the signature. Go automatically initializes these variables to their respective zero values upon function invocation. A return statement without arguments (a “naked return”) implicitly returns the current state of these named variables.
func split(sum int) (x, y int) {
    x = sum * 4 / 9
    y = sum - x
    return // implicitly returns x and y
}

Anonymous Functions and Closures

Functions can be declared without an identifier. These anonymous functions can be executed immediately (IIFE) or assigned to variables. Because an IIFE is an expression, it can be executed at the package level to initialize global variables, or it can be executed locally within a function body.
// Package-level IIFE initializing a global variable
var status = func() string {
    return "initialized"
}()

func execute() {
    // Local IIFE
    func(msg string) {
        println(msg)
    }("Execution complete")
}
Anonymous functions in Go act as closures. They capture and bind to variables from their surrounding lexical scope. The closure maintains a reference to these captured variables, allowing them to be accessed and mutated even after the outer function has returned.
func counter() func() int {
    count := 0
    return func() int {
        count++ // captures and mutates the outer 'count' variable
        return count
    }
}

Function Types

Because functions are first-class types, their signatures can be aliased or defined as custom types using the type keyword. This enforces strict type checking when passing functions as arguments.
type BinaryOperation func(int, int) int

func executeOp(a, b int, op BinaryOperation) int {
    return op(a, b)
}

Deferred Execution

The defer statement pushes a function call onto an internal stack. When the surrounding function completes—either by executing a return statement, reaching the end of its body, or panicking—the deferred functions are popped and executed in Last-In-First-Out (LIFO) order. Arguments to deferred functions are evaluated immediately when the defer statement is executed, not when the actual function call occurs.
func executeTask() {
    defer println("Cleanup phase") // Executes second
    println("Execution phase")     // Executes first
}

Panic and Recover

Go provides built-in mechanisms for handling exceptional control flow within function boundaries.
  • Panic: The panic built-in function halts normal execution. When a function calls panic, its execution stops, any deferred functions are executed normally, and then control returns to its caller. This unwinding process continues up the stack until the program crashes.
  • Recover: The recover built-in function regains control of a panicking goroutine. recover is only effective when called directly inside a deferred function. If the current goroutine is panicking, recover captures the value passed to panic and halts the unwinding sequence, allowing normal execution to resume from the point immediately after the function containing the defer.
package main

import "fmt"

func safeExecute() {
    defer func() {
        if r := recover(); r != nil {
            fmt.Println("Recovered from panic:", r)
        }
    }()
    
    panic("unexpected state")
    // Code below panic is unreachable
}

func main() {
    safeExecute()
    fmt.Println("Normal execution resumes")
}
Master Go with Deep Grasping Methodology!Learn More