• linkedu视频
  • 平面设计
  • 电脑入门
  • 操作系统
  • 办公应用
  • 电脑硬件
  • 动画设计
  • 3D设计
  • 网页设计
  • CAD设计
  • 影音处理
  • 数据库
  • 程序设计
  • 认证考试
  • 信息管理
  • 信息安全
菜单
linkedu.com
  • 网页制作
  • 数据库
  • 程序设计
  • 操作系统
  • CMS教程
  • 游戏攻略
  • 脚本语言
  • 平面设计
  • 软件教程
  • 网络安全
  • 电脑知识
  • 服务器
  • 视频教程
  • vbs
  • DOS/BAT
  • hta/htc
  • python
  • perl
  • VBA
  • ColdFusion
  • ruby
  • PowerShell
  • Lua
  • Golang
  • linux shell
您的位置:首页 > 脚本语言 >Golang > 深入理解Go语言中的闭包

深入理解Go语言中的闭包

作者:daisy 字体:[增加 减小] 来源:互联网

daisy 通过本文主要向大家介绍了c语言传递闭包,闭包的理解,js闭包的理解,如何理解闭包,如何理解js闭包等相关知识,希望对您有所帮助,也希望大家支持linkedu.com www.linkedu.com

闭包

在函数编程中经常用到闭包,闭包是什?它是怎么产生的及用来解决什么问题呢?先给出闭包的字面定义:闭包是由函数及其相关引用环境组合而成的实体(即:闭包=函数+引用环境)。这个从字面上很难理解,特别对于一直使用命令式语言进行编程的程序员们。

Go语言中的闭包

先看一个demo:

func f(i int) func() int {
 return func() int {
 i++
 return i
 }
}
</div>

函数f返回了一个函数,返回的这个函数就是一个闭包。这个函数中本身是没有定义变量i的,而是引用了它所在的环境(函数f)中的变量i。

我们再看一下效果:

c1 := f(0)
c2 := f(0)
c1() // reference to i, i = 0, return 1
c2() // reference to another i, i = 0, return 1
</div>

c1跟c2引用的是不同的环境,在调用i++时修改的不是同一个i,因此两次的输出都是1。函数f每进入一次,就形成了一个新的环境,对应的闭包中,函数都是同一个函数,环境却是引用不同的环境。

变量i是函数f中的局部变量,假设这个变量是在函数f的栈中分配的,是不可以的。因为函数f返回以后,对应的栈就失效了,f返回的那个函数中变量i就引用一个失效的位置了。所以闭包的环境中引用的变量不能够在栈上分配。

escape analyze

在继续研究闭包的实现之前,先看一看Go的一个语言特性:

func f() *Cursor {
 var c Cursor
 c.X = 500
 noinline()
 return &c
}
</div>

Cursor是一个结构体,这种写法在C语言中是不允许的,因为变量c是在栈上分配的,当函数f返回后c的空间就失效了。但是,在Go语言规范中有说明,这种写法在Go语言中合法的。语言会自动地识别出这种情况并在堆上分配c的内存,而不是函数f的栈上。

为了验证这一点,可以观察函数f生成的汇编代码:

MOVQ $type."".Cursor+0(SB),(SP) // 取变量c的类型,也就是Cursor
PCDATA $0,$16
PCDATA $1,$0
CALL ,runtime.new(SB) // 调用new函数,相当于new(Cursor)
PCDATA $0,$-1
MOVQ 8(SP),AX // 取c.X的地址放到AX寄存器
MOVQ $500,(AX) // 将AX存放的内存地址的值赋为500
MOVQ AX,"".~r0+24(FP)
ADDQ $16,SP
</div>

识别出变量需要在堆上分配,是由编译器的一种叫escape analyze的技术实现的。

如果输入命令:

go build --gcflags=-m main.go
</div>

可以看到输出:

注意:最后两行,标识c逃逸了,被移动到堆中。escape analyze可以分析出变量的作用范围,这是对垃圾回收很重要的一项技术。

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作能带来一定的帮助,如果有疑问大家可以留言交流。

</div>

您可能想查找下面的文章:

  • 深入理解Go语言中的闭包
  • 举例讲解Go语言中函数的闭包使用
  • 简单了解Go语言中函数作为值以及函数闭包的使用

相关文章

  • Go语言生成素数的方法
  • Go语言常见哈希函数的使用
  • 利用Go语言搭建WebSocket服务端方法示例
  • GO语言实现简单的目录复制功能
  • Go语言单链表实现方法
  • Go语言中的指针运算实例分析
  • Go语言中的方法、接口和嵌入类型详解
  • 在Visual Studio Code中配置GO开发环境的详细教程
  • go语言执行等待直到后台goroutine执行完成实例分析
  • go语言实现顺序存储的栈

文章分类

  • vbs
  • DOS/BAT
  • hta/htc
  • python
  • perl
  • VBA
  • ColdFusion
  • ruby
  • PowerShell
  • Lua
  • Golang
  • linux shell

最近更新的内容

    • Go语言字典(map)用法实例分析【创建,填充,遍历,查找,修改,删除】
    • Go语言获取本机逻辑CPU数量的方法
    • Go语言常见哈希函数的使用
    • GO语言基础之数组
    • Go语言扫描目录并获取相关信息的方法
    • Go语言MD5加密用法实例
    • Go语言中错误处理实例分析
    • go语言检测文件是否存在的方法
    • Go语言服务器开发之简易TCP客户端与服务端实现方法
    • GO语言获取系统环境变量的方法

关于我们 - 联系我们 - 免责声明 - 网站地图

©2020-2025 All Rights Reserved. linkedu.com 版权所有