无论是什么语言,函数都是最常被使用到的东西。
我们对比一下 Golang 和 C 这两种语言的函数实现,进而我们能真正理解以下两个问题。
- 为什么 C 语言只能有一个返回值,而 Golang 中可以返回多个?
- Golang 函数调用在性能上和 C 比有何差异?
一、C 语言函数深究
我们准备一段简单的函数调用代码。
#include
int func(int p){
return 1;
}
int main()
{
int i;
for(i=0; i main.s
结果是这样的:
"".main STEXT size=95 args=0x0 locals=0x38
0x000f 00015 (main.go:7) SUBQ $56, SP //在栈上分配56字节
0x0013 00019 (main.go:7) MOVQ BP, 48(SP) //保存BP
0x0018 00024 (main.go:7) LEAQ 48(SP), BP
0x001d 00029 (main.go:8) MOVQ $1, (SP) //第一个参数入栈
0x0025 00037 (main.go:8) MOVQ $2, 8(SP) //第二个参数入栈
0x002e 00046 (main.go:8) MOVQ $3, 16(SP) //第三个参数入栈
0x0037 00055 (main.go:8) MOVQ $4, 24(SP) //第四个参数入栈
0x0040 00064 (main.go:8) MOVQ $5, 32(SP) //第五个参数入栈
0x0049 00073 (main.go:8) CALL "".myFunction(SB)
"".myFunction STEXT nosplit size=99 args=0x38 locals=0x18
0x000e 00014 (main.go:3) MOVQ $0, "".~r5+72(SP)
0x0017 00023 (main.go:3) MOVQ $0, "".~r6+80(SP)
0x0020 00032 (main.go:4) MOVQ "".p1+32(SP), AX
0x0025 00037 (main.go:4) ADDQ "".p2+40(SP), AX
0x002a 00042 (main.go:4) ADDQ "".p3+48(SP), AX
0x002f 00047 (main.go:4) ADDQ "".p4+56(SP), AX
0x0034 00052 (main.go:4) ADDQ "".p5+64(SP), AX
0x004b 00075 (main.go:6) MOVQ AX, "".~r5+72(SP)
0x0054 00084 (main.go:6) MOVQ AX, "".~r6+80(SP)
可以看到,在Golang中:
使用栈来传递参数 栈是位于内存之中的,虽然有 CPU 中 L1、L2、L3的帮助,但平均每次访问性能仍然和寄存器没法比。所以 Golang 的函数调用开销肯定会比 C 语言要高。后面我们将用一个实验来进行量化的比较。
使用栈来返回数据 不像 C 语言那样固定使用一个 eax 寄存器,Golang 是使用栈来返回值的。这就是为啥 Golang 可以返回多个值的根本原因。
最后,性能开销对比
我们的测试方法简单粗暴,直接调用空函数 1 亿次,再统计计算平均耗时。
C函数编译运行测试:
#include
int func(int p){
return 1;
}
int main()
{
int i;
for(i=0; i