Go 语言递归函数

基线条件、递归 vs 迭代、尾递归为何不被优化、记忆化。

Intermediate
Key Points递归必须有基线条件;Go 不做尾调用优化,深递归会爆栈。

基本形态

Go
func factorial(n int) int {
	if n <= 1 {          // 基线条件
		return 1
	}
	return n * factorial(n-1)    // 递归调用
}

fmt.Println(factorial(5))
fmt.Println(factorial(10))
Output
120
3628800

Writing recursion needs two answers: when to stop (base case) and how to shrink the problem (recursive step). Once both are clear the code is three lines.

斐波那契:从慢到快

Go
// 朴素递归:O(2^n),n=40 就要几秒
func fibSlow(n int) int {
	if n < 2 {
		return n
	}
	return fibSlow(n-1) + fibSlow(n-2)
}

// 记忆化:O(n)
func fibMemo(n int, cache map[int]int) int {
	if n < 2 {
		return n
	}
	if v, ok := cache[n]; ok {
		return v
	}
	r := fibMemo(n-1, cache) + fibMemo(n-2, cache)
	cache[n] = r
	return r
}

fmt.Println(fibSlow(10))
fmt.Println(fibMemo(50, map[int]int{}))
Output
55
12586269025

fibSlow(50) would take roughly 40 billion calls; the memoised version is instant. Recursion is not slow — repeated subproblems are.

递归 vs 迭代

AspectRecursionIteration
可读性树、图遍历时更直观线性逻辑更清楚
内存每次调用压栈常量空间
性能有函数调用开销更快
深度受栈大小限制几乎无限制
Go
// 迭代版:省栈,快一倍
func factorialIter(n int) int {
	r := 1
	for i := 2; i <= n; i++ {
		r *= i
	}
	return r
}

Go 不做尾递归优化

Go
// 尾递归写法,在 Scheme/Haskell 里会被优化成循环
func sumTail(n, acc int) int {
	if n == 0 {
		return acc
	}
	return sumTail(n-1, acc+n)
}

// Go 不会优化,n 很大时栈溢出
// runtime: goroutine stack exceeds 1000000000-byte limit
Goroutine stacks grow dynamically (2 KB up to 1 GB), so they survive deeper recursion than C's 8 MB stack. But that is growth, not optimisation — sumTail(10000000) still dies. Rewrite deep recursion as a loop.

树遍历

Go
type Node struct {
	Val         int
	Left, Right *Node
}

func (n *Node) InOrder(visit func(int)) {
	if n == nil {
		return
	}
	n.Left.InOrder(visit)
	visit(n.Val)
	n.Right.InOrder(visit)
}

root := &Node{2, &Node{1, nil, nil}, &Node{3, nil, nil}}
root.InOrder(func(v int) { fmt.Print(v, " ") })
fmt.Println()
Output
1 2 3 

Recursion is the natural fit for tree traversal; an iterative version needs a hand-managed stack. For problems whose structure is recursive, recursion earns its cost.

Friends & Partners