教程集 www.jiaochengji.com
教程集 >  Golang编程  >  golang教程  >  正文 理解 Golang 中函数调用的原理

理解 Golang 中函数调用的原理

发布时间:2021-12-22   编辑:jiaochengji.com
教程集为您提供理解 Golang 中函数调用的原理等资源,欢迎您收藏本站,我们将为您提供最新的理解 Golang 中函数调用的原理资源

函数是 Go 语言中的一等公民,理解和掌握函数的调用过程是深入学习 Golang 时无法跳过的步骤,这里会介绍 Go 语言中函数调用的过程和实现原理并与 C 语言中函数执行的过程进行对比,同时对参数传递的原理进行剖析,让读者能够清楚地知道 Go 在函数的执行过程中究竟都做了哪些工作。

本文将从函数的调用惯例和参数的传递方法两个方面分别介绍函数的执行过程,同时在这里会默认阅读这篇文章的读者已经掌握了 栈、寄存器 等概念,文章并不会就这两部分内容展开进行介绍。

<h2 id="调用惯例"> <span class="octicon octicon-link"/>调用惯例</h2>

在计算机科学中,调用惯例其实就是指在实现层面上,一个函数(子程序)如何接受主程序传递的参数并如何将返回值传递回主程序。不同语言对于传递参数和返回值的实现上会有一些差异,不过无论是在 C、Go 语言这种比较接近系统的编程语言,还是 Ruby、Python 这类语言,它们在<em>函数调用</em>上往往都具有相同的形式,也就是一般包含函数名、参数列表两个部分:

<pre><code class="lang-c hljs">somefunction(arg0, arg1) </code></code></pre>

虽然它们的调用形式看起来差不多,但是在这里我们需要考虑 C 和 Go 这两门语言究竟是如何实现调用惯例的,这对于我们理解的 Go 语言的函数调用原理会有非常大的帮助。

<h3 id="c-语言"> <span class="octicon octicon-link"/>C 语言</h3>

如果想要了解 C 语言中的函数调用的原理,我们可以通过 gcc 或者 clang 将 C 语言的代码编译成汇编语言,从汇编语言中可以一窥函数调用的具体过程,作者使用的是编译器和内核的版本如下:

<pre><code class="lang-bash hljs">$ gcc --version gcc (Ubuntu 4.8.2-19ubuntu1) 4.8.2 Copyright (C) 2013 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. $ uname -a Linux iZ255w13cy6Z 3.13.0-32-generic #57-Ubuntu SMP Tue Jul 15 03:51:08 UTC 2014 x86_64 x86_64 x86_64 GNU/Linux </code></code></pre> <blockquote>

gcc 和 clang 虽然在编译 C 语言代码时生成的汇编语言可能有比较大的差别,但是生成代码的结构不会有太大的区别,需要注意的是不同内核版本的操作系统生成的汇编指令可能有比较大的不同,不过对于我们这些只是想要了解实现原理的开发者来说没有太多的影响。

</blockquote>

假设我们有以下的 C 语言代码,代码中只包含两个函数,其中一个是主函数 <code>main</code>,另一个就是我们定义的函数 <code>my_function</code>,代码非常简单:

<pre><code class="lang-c hljs">int my_function(int arg1, int arg2) { return arg1 arg2; } int main() { int i = my_function(1, 2); } </code></code></pre>

接下来我们可以使用 <code>gcc -S main.c</code> 将当前的文件编译成包含汇编语言的 <code>main.s</code> 文件,为了减少一些与函数调用无关的噪音,我们将生成的汇编代码经过一些简单地删减展示出来:

<pre><code class="lang-c hljs">my_function: .LFB0: .cfi_startproc pushq %rbp .cfi_def_cfa_offset 16 .cfi_offset 6, -16 movq %rsp, %rbp .cfi_def_cfa_register 6 movl

您可能感兴趣的文章:
理解 Golang 中函数调用的原理
探索Golang协程实现——从v1.0开始
关于Golang的那些事(五) -- 函数
想系统学习GO语言(Golang
Golang - 访问数据库报错后程序继续运行
go 协程
Golang面试题总结
golang的协程原理
Golang协程原理(一)
golang的调度总结

[关闭]
~ ~