深入分析深入分析golang多值返回以及闭包的实现多值返回以及闭包的实现
相对于C/C++,golang有很多新颖的特性,例如goroutine,channel等等,这些特性其实从golang源码是可以理解
其实现的原理。今天这篇文章主要来分析下golang多值返回以及闭包的实现,因为这两个实现golang源码中并
不存在,我们必须从汇编的角度来窥探二者的实现。
一、前言一、前言
golang有很多新颖的特性,不知道大家的使用的时候,有没想过,这些特性是如何实现的?当然你可能会说,不了解这些特性
好像也不影响自己使用golang,你说的也有道理,但是,多了解底层的实现原理,对于在使用golang时的眼界是完全不一样
的,就类似于看过http的实现之后,再来使用http框架,和未看过http框架时的眼界是不一样的,当然,你如果是一名it爱好
者,求知欲自然会引导你去学习。
二、这篇文章主要就分析两点二、这篇文章主要就分析两点:
1、、golang多值返回的实现多值返回的实现;
2、、golang闭包的实现闭包的实现;
三、三、golang多值返回的实现多值返回的实现
我们在学C/C++时,很多人应该有了解过C/C++函数调用过程,参数是通过寄存器di和si(假设就两个参数)传递给被调用的函
数,被调用函数的返回结果只能是通过eax寄存器返回给调用函数,因此C/C++函数只能返回一个值,那么我们是不是可以想
象,golang的多值返回是否可以通过多个寄存器来实现的,正如用多个寄存器来传参一样?
这也是一种办法,但是golang并没有采用;我的理解是引入多个寄存器来存储返回值,会引起多个寄存器用途的重新约定,这
无疑增加了复杂度;可以这么说,golang的ABI与C/C++非常不一样;
在从汇编角度分析golang多值返回之前,需要先熟悉golang汇编代码的一些约定, golang官网 有说明,这里重点说明四个
symbols,需要注意的是这里的寄存器是伪寄存器:
1.FP 栈底寄存器,指向一个函数栈的顶部;
2.PC 程序计数器,指向下一条执行指令;
3.SB 指向静态数据的基指针,全局符号;
4.SP 栈顶寄存器;
这里面最重要的就是FP和SP,FP寄存器主要用于取参数以及存返回值,golang函数调用的实现很大程度上都是依赖这两个寄
存器,这里先给出结果,
+-----------+---\
| 返回值2 | \
+-----------+ \
| 返回值1 | \
+---------+-+
| 参数2 | 这些在调用函数中
+-----------+
| 参数1 | /
+-----------+ /
| 返回地址 | /
+-----------+--\/-----fp值
| 局部变量 | \
| ... | 被调用数栈祯
| | /
+-----------+--/+---sp值
这个就是golang的一个函数栈,也是说函数传参是通过fp+offset来实现的,而多个返回值也是通过fp+offset存储在调用函数的栈
帧中。
下面通过一个例子来分析
package main
import "fmt"
func test(i, j int) (int, int) {
a:=i+ j
b:=i- j
return a,b
}
func main() {