[Golang]尾递归优化?
参考
- 尾调用详解 - 阮一峰
- go&plan9 - 曹大
什么是尾调用
```func g(n int) {fmt.Println(n)}func f(m int) {m++g(m)}在f()函数内最后直接调用g()
```
尾调用优化
- 我们把调用函数称作caller,被调用函数称作callee
- 在程序运行过程中,需要先保存caller现场在栈帧中,然后调用callee。caller栈帧会在callee调用返回后,继续执行完毕,然后释放
- 但是,在尾调用中,callee在caller的最后,所以caller的栈帧其实在callee调用前就可以释放了,优化的目的也是为此
- 提前释放释放caller栈帧,可大大减少内存使用,同时避免了调用层级过多导致的栈空间爆炸
- 对plan9汇编和栈帧概念不熟悉的同学可以参考这篇译文go&plan9
尾递归调用
```func f(n int) {fmt.Println(n)n++f(n)}尾递归调用:在f()函数内最后再调用自己在C++等的O2级别优化中,一般会被优化为for循环
```
golang编译器是否会做尾递归优化
- 从实验结果来看,不会做优化
验证方法一:查看汇编代码
- 写一个尾递归函数
- [外链图片转存中…(img-ZUiRLmHF-1614241682059)]
- go tool compile -S demo.go
- [外链图片转存中…(img-DR4FoyHZ-1614241682061)]
验证方法二:编译运行
- 写一个尾递归函数,递归层级搞的足够大
- [外链图片转存中…(img-U8jMykaF-1614241682062)]
- go run demo.go
- [外链图片转存中…(img-xHzWnOh8-1614241682064)]
- 内存爆炸!!! - 说明没有优化#### 参考
- 尾调用详解 - 阮一峰
- go&plan9 - 曹大
什么是尾调用
```func g(n int) {fmt.Println(n)}func f(m int) {m++g(m)}在f()函数内最后直接调用g()
```
尾调用优化
- 我们把调用函数称作caller,被调用函数称作callee
- 在程序运行过程中,需要先保存caller现场在栈帧中,然后调用callee。caller栈帧会在callee调用返回后,继续执行完毕,然后释放
- 但是,在尾调用中,callee在caller的最后,所以caller的栈帧其实在callee调用前就可以释放了,优化的目的也是为此
- 提前释放释放caller栈帧,可大大减少内存使用,同时避免了调用层级过多导致的栈空间爆炸
尾递归调用
```func f(n int) {fmt.Println(n)n++f(n)}尾递归调用:在f()函数内最后再调用自己在C++等的O2级别优化中,一般会被优化为for循环
```
golang编译器是否会做尾递归优化
- 从实验结果来看,不会做优化
验证方法一:查看汇编代码
写一个尾递归函数
go tool compile -S demo.go 生成go-plan9汇编
验证方法二:编译运行
写一个尾递归函数,递归层级搞的足够大
go run demo.go
Boom!!! 内存爆炸!!!说明Golang编译器针对尾递归没有优化
[Golang]尾递归优化?相关推荐
- Kotlin尾递归优化
一.尾递归优化 1.递归的一种特殊形式 2.调用自身后无其他的操作 3.tailrec关键字提示编译器尾递归优化 二.具体的来看看一下代码说明 package net.println.kotlin.c ...
- javascript --- 尾递归优化的实现
考虑一个正常的递归函数 function sum(x, y) {if (y > 0) {return sum (x + 1, y - 1);} else {return x;} } sum(1, ...
- python 函数式编程尾递归优化 day16
函数编程的特征: 1不可变:不用变量保存状态,不修改变量 #非函数式 a = 1 def incr_test1():global a#一旦更改全局变量后后面再调用a就容易乱a += 1return a ...
- 尾递归优化原理与Python实现(以Fibonacci数列和小明爬楼梯问题为例)
首先祝全体屋友中秋节快乐! 众所周知,在函数递归调用时,要保存函数调用的位置以便使得被调函数结束后能够返回正确的位置,这个信息保存在线程栈中.由于栈的空间有限,所以如果函数递归调用深度超过一定限制,会 ...
- 尾递归优化 - 尾递归优化
原理 调用一个函数时,就会形成一个调用帧:在A函数内部执行B函数:当调用A函数时形成一个A的调用帧,在A函数内部调用B函数,在A调用帧上又会生成B调用帧,B执行完毕时B调用帧消失,A完毕后A调用帧消失 ...
- python递归_Python开启尾递归优化!
Python尾递归优化 一般递归与尾递归 一般递归: def normal_recursion(n): if n == 1: return 1 else: return n + normal_recu ...
- ES6 尾调用和尾递归优化
尾调用 尾调用(Tail Call)是函数式编程的一个重要概念,就是指某个函数的最后一步是调用另一个函数. function fun(x){return a(x); } 上面代码中,函数fun的最后一 ...
- java实现尾递归优化,你们都知道递归,尾递归呢?什么又是尾递归优化?
你们都知道递归,尾递归呢?什么又是尾递归优化? 码农唐磊 程序猿石头 今天,咱们来聊聊递归函数.为啥忽然想到递归?其实就从电影名字<恐怖游轮><盗梦空间>想到了.图片java ...
- 大家都知道递归,尾递归呢?什么又是尾递归优化?
点击上方蓝色字体,关注我 -- 一个在阿里云打工的清华学渣! 今天,我们来聊聊递归函数.为啥突然想到递归?其实就从电影名字<恐怖游轮><盗梦空间>想到了. 递归是啥? 递归函数 ...
最新文章
- Spark2.x写入Elasticsearch的性能测试
- 文件上传(上传至独立的文件服务器)
- iOS程序启动过程笔记
- 18亿用户、10万条电源线、4200万月活......创业者的底限究竟在哪里?
- android获取QQ昵称,【Ctrl.js】QQ读取好友昵称和QQ号源码
- 7.4.4 主成分分析 PCA
- 在欲而无欲,居尘不染尘
- JPA和Hibernate级联类型的初学者指南
- bat 存储过程返回值_MySQL-存储过程和函数详述
- [轉]VS2010 UML类图生成代码
- 使括号有效的最少添加
- JAVA创建对象有哪几种方式
- 华为交换机双上行组网Smart-link配置指南
- 工具类——FileUtils
- 嵌入式系统课堂总结1
- 四只头雁:5G to B规模商用的开启节点
- wlan从入门到精通第六期STA接入过程
- 【数据结构】栈和队列
- Chipsec UEFI Shell启动盘的制作与使用,让你可以在所有平台轻松使用Chipsec
- 基于金字塔LK的光流法实现—根据论文自己实现的c++代码