Basic Recursion
Here’s a classic example of recursion - calculating factorial:fact(0).
Every recursive function needs a base case (a condition that stops the recursion) to avoid infinite loops and stack overflow errors.
How Recursion Works
When you callfact(7), the execution flow looks like this:
Recursive Anonymous Functions
Anonymous functions can also be recursive, but this requires explicitly declaring a variable to store the function:The variable
fib must be declared with var before the function is defined. This allows Go to know which function to call when fib is referenced inside the anonymous function.Complete Example
Common Recursive Patterns
Tree Traversal
List Processing
Tail Recursion Optimization
Go doesn’t guarantee tail call optimization, so deeply recursive functions can cause stack overflow. Consider using iteration or helper functions with accumulators:Memoization for Recursive Functions
Some recursive functions (like Fibonacci) recalculate the same values repeatedly. Memoization can dramatically improve performance:Mutual Recursion
Multiple functions can call each other recursively:Best Practices
Always define a base case
Always define a base case
Every recursive function must have a condition that stops the recursion:
Consider recursion depth
Consider recursion depth
Go’s default stack size is limited. For potentially deep recursion, validate input or use iteration:
Use recursion when it makes code clearer
Use recursion when it makes code clearer
Recursion is ideal for naturally recursive problems (trees, graphs, divide-and-conquer), but iteration may be clearer for simple loops.
Consider performance implications
Consider performance implications
Recursive functions have overhead from function calls. For performance-critical code or deep recursion, consider iterative alternatives.
When to Use Recursion
- Tree and graph traversal
- Divide-and-conquer algorithms (quicksort, mergesort)
- Problems with recursive structure (Fibonacci, factorial)
- Backtracking algorithms
- Parsing nested structures
When to Avoid Recursion
- Simple iteration would be clearer
- Very deep recursion (risk of stack overflow)
- Performance-critical tight loops
- When Go’s lack of tail call optimization is problematic
Key Takeaways
- Recursive functions call themselves to solve subproblems
- Every recursive function needs a base case to terminate
- Anonymous functions can be recursive with proper variable declaration
- Go doesn’t optimize tail recursion - consider iteration for deep recursion
- Memoization can dramatically improve recursive function performance
- Use recursion when it makes the problem clearer, not just because you can