Go语言的递归函数

一、什么是递归函数?

递归函数

函数在自己的函数体中 调用自己

递归 =

  • 当前问题 拆成

  • 更小规模的同类问题

  • 直到一个 终止条件(base case)

少了终止条件,程序就会「无限套娃」直接栈溢出 。

二、Go 递归函数的基本结构

Go 中递归函数 和普通函数写法完全一样,没有任何特殊语法。

Go 复制代码
func f(...) 返回值 {
    // 1. 终止条件
    if 条件 {
        return 某个值
    }

    // 2. 递归调用
    return f(更小的问题)
}

三、最经典例子:阶乘(Factorial)

数学定义

n! = n × (n-1)!

0! = 1

Go 实现

Go 复制代码
func factorial(n int) int {
    if n == 0 {
        return 1 // 终止条件
    }
    return n * factorial(n-1)
}

调用

Go 复制代码
fmt.Println(factorial(5)) // 120

四、递归一定要有的 2 个要素

1. 终止条件(base case)

Go 复制代码
if n == 0 {
    return 1
}

否则会导致栈溢出

2. 规模缩小

Go 复制代码
factorial(n-1)

每次调用都 更接近终止条件

五、进阶点:斐波那契数列

定义

f(0) = 0

f(1) = 1

f(n) = f(n-1) + f(n-2)

Go 实现

Go 复制代码
//1、声明
func fib(n int) int {
    if n <= 1 {
        return n
    }
    return fib(n-1) + fib(n-2)
}


//2、调用
fmt.Println(fib(6)) // 输出8

注意

这个写法在 n 大时 性能很差(重复计算)

六、递归在 Go 中的常见使用场景

1. 树 / 目录结构遍历

Go 复制代码
type Node struct {
    Val      int
    Children []*Node
}

func dfs(node *Node) {
    if node == nil {
        return
    }
    fmt.Println(node.Val)
    for _, child := range node.Children {
        dfs(child)
    }
}

2. 文件系统递归遍历

Go 复制代码
func walkDir(path string) {
    files, _ := os.ReadDir(path)
    for _, f := range files {
        fullPath := filepath.Join(path, f.Name())
        if f.IsDir() {
            walkDir(fullPath)
        } else {
            fmt.Println(fullPath)
        }
    }
}

3. 分治算法

  • 快速排序

  • 归并排序

  • 二分查找

七、递归 vs for 循环(Go 实战视角)

对比点 递归 循环
代码可读性 ⭐⭐⭐⭐ ⭐⭐⭐
写起来 简洁 稍繁琐
性能 一般 ⭐⭐⭐⭐
栈风险

Go 实战建议

  • 层级浅、逻辑清晰 用递归

  • 层级深、频繁调用 用循环或显式栈

八、Go 的一个小坑:没有尾递归优化

Go 不保证尾递归优化(不像某些函数式语言)

尾递归示例(但 Go 依然会压栈)

Go 复制代码
func sum(n, acc int) int {
    if n == 0 {
        return acc
    }
    return sum(n-1, acc+n)
}

即使是尾递归,
栈深度依然增长,大数据量要小心。

相关推荐
用户605723748730815 小时前
AI 编码助手的规范驱动开发 - OpenSpec 初探
前端·后端·程序员
哈密瓜的眉毛美15 小时前
零基础学Java|第二篇:Java 核心机制与第一个程序:从 JVM 到 Hello World
后端
用户83071968408215 小时前
RabbitMQ vs RocketMQ 事务大对决:一个在“裸奔”,一个在“开挂”?
后端·rabbitmq·rocketmq
初次攀爬者15 小时前
RocketMQ 集群介绍
后端·消息队列·rocketmq
Leo89915 小时前
go 从零单排 之 一小时通关
后端
花花无缺15 小时前
搞懂@Autowired 与@Resuorce
java·spring boot·后端
CodeMonkey15 小时前
记一次傻逼一样的 OOM 异常
后端
初次攀爬者15 小时前
RocketMQ 基础学习
后端·消息队列·rocketmq
重庆穿山甲15 小时前
Java开发者的大模型入门:LangChain4j组件全攻略(二)
后端
重庆穿山甲16 小时前
Java开发者的大模型入门:LangChain4j组件全攻略(一)
后端