Go 闭包捕获问题
在 Go 语言中,闭包(closure)是一个函数值,它引用了其外部作用域中的变量。简而言之,闭包能够“捕获”并“记住”其外部作用域中的变量,即使这个变量的生命周期已经结束。闭包的这种特性使得它在许多编程场景中非常有用,但也可能导致一些意外行为,尤其是在捕获变量时。
捕获问题的例子
一个常见的捕获问题是循环变量的捕获。下面是一个经典的例子:
package main
import "fmt"
func main() {
var funcs []func()
for i := 0; i < 3; i++ {
funcs = append(funcs, func() {
fmt.Println(i)
})
}
for _, f := range funcs {
f()
}
}
你可能期望这个程序输出 0, 1, 2,但实际上它会输出 3, 3, 3。原因在于闭包捕获的是变量 i 的引用,而不是它的值。循环结束后,i 的最终值是 3,因此所有的闭包都引用的是这个最终值。
解决方法
要解决这个问题,可以通过在每次迭代中创建一个新的变量来捕获当前的值:
package main
import "fmt"
func main() {
var funcs []func()
for i := 0; i < 3; i++ {
i := i // 重新声明一个新的 `i` 变量
funcs = append(funcs, func() {
fmt.Println(i)
})
}
for _, f := range funcs {
f()
}
}
或者使用一个辅助函数:
package main
import "fmt"
func main() {
var funcs []func()
for i := 0; i < 3; i++ {
funcs = append(funcs, createFunc(i))
}
for _, f := range funcs {
f()
}
}
func createFunc(i int) func() {
return func() {
fmt.Println(i)
}
}
在这两个示例中,每个闭包都捕获了不同的 i 值,这样就能得到期望的输出 0, 1, 2。
总结
闭包捕获变量时,容易出现捕获变量引用而不是值的问题。特别是在循环中,这种问题更容易发生。通过在每次迭代中创建一个新的变量或者使用辅助函数,可以有效地避免这种问题。理解闭包的捕获机制对于编写正确且高效的 Go 代码非常重要。
Go 闭包捕获问题的更多相关文章
- go语言基础之闭包捕获外部变量特点
1.闭包捕获外部变量特点 示例: package main //必须 import "fmt" func main() { a := 10 str := "mike&qu ...
- C#的闭包捕获变量与英语中Nice to meet you的联系
看标题有种"意大利面与42号混凝土"放在一起说的感觉,实际上,就是. 闭包捕获变量 我们都知道在C#里,闭包捕获的是变量,而不是变量值本身 每个Task在运行的时候,发现i的值是3 ...
- swift 学习(二)基础知识 (函数,闭包,ARC,柯里化,反射)
函数 func x(a:Int, b:Int) {} func x(a:Int, b:Int) -> Void {} func x(a:Int, b:Int) ->(Int,Int ...
- JavaScript之作用域与闭包详解
前言: JavaScript是一种应用非常广泛的语言,其也有一些自身特点和优势,本文重在讲述其作用域机制以及闭包,会从一些实例来探讨其机理. 作用域在JavaScript程序员日常使用中有不同的含义, ...
- iOS - Swift Closure 闭包
1.Closure 闭包在 Swift 中非常有用.通俗的解释就是一个 Int 类型里存储着一个整数,一个 String 类型包含着一串字符,同样,闭包是一个包含着函数的类型.有了闭包,你就可以处理很 ...
- 什么是JavaScript闭包终极全解之一——基础概念
本文转自:http://www.cnblogs.com/richaaaard/p/4755021.html 什么是JavaScript闭包终极全解之一——基础概念 “闭包是JavaScript的一大谜 ...
- scala学习笔记(6):闭包
到本章这里,所有函数文本的例子仅参考了传入的参数.例如,(x: Int) => x > 0里,函数体用到的唯一变量,x > 0,是x,被定义为函数参数.然而也可以参考定义在其它地方的 ...
- Scala闭包
假如我们定义如下的函数: (x:Int) => x + more 这里我们引入一个自由变量more.它不是所定义函数的参数,而这个变量定义在函数外面,比如: var more =1 那么我们有如 ...
- 闭包 -> map / floatMap / filter / reduce 浅析
原创: 转载请注明出处 闭包是自包含的函数代码块,可以在代码中被传递和使用 闭包可以捕获和存储其所在上下文中任意常量和变量的引用.这就是所谓的闭合并包裹着这些常量和变量,俗称闭包.Swift 会为您管 ...
- go语言学习--go中闭包
Go语言支持匿名函数,即函数可以像普通变量一样被传递或使用. 使用方法如下: package main import ( "fmt" ) func main() { var v f ...
随机推荐
- 【Autoware】Autoware安装教程
此篇主要是从自己的csdn copy 在博客园上备份一下哈~ 前提:大家需要换源[软件源和pip源]:git clone的时候走博主给的Gitee的链接吧 不然得等个十万年... 如果想看最终是啥样的 ...
- 建立Model
直接使用Sequelize虽然可以,但是存在一些问题. 团队开发时,有人喜欢自己加timestamp: var Pet = sequelize.define('pet', { id: { type: ...
- mac电脑好用的工具总结
制作gif:https://gfycat.com/gifbrewery 制作gif(超级好用,制作速度快,压缩图片小):https://www.cockos.com/licecap/ 解压工具:htt ...
- 记一次 .NET某酒业业务系统 崩溃分析
一:背景 1. 讲故事 前些天有位朋友找到我,说他的程序每次关闭时就会自动崩溃,一直找不到原因让我帮忙看一下怎么回事,这位朋友应该是第二次找我了,分析了下 dump 还是挺经典的,拿出来给大家分享一下 ...
- idea使用git管理项目(Mac版)
1.本地安装git mac版 breaw install git 查看是否安装成功 git --version 这样就成功了,一般是自带的有 windows版 https://www.cnblogs. ...
- 机器学习:详解是否要使用端到端的深度学习?(Whether to use end-to-end learning?)
详解是否要使用端到端的深度学习? 假设正在搭建一个机器学习系统,要决定是否使用端对端方法,来看看端到端深度学习的一些优缺点,这样就可以根据一些准则,判断的应用程序是否有希望使用端到端方法. 这里是应用 ...
- 7月24号python:库存管理
7月24号python:库存管理 题目: 仓库管理员以数组 stock 形式记录商品库存表.stock[i] 表示商品 id,可能存在重复.原库存表按商品 id 升序排列.现因突发情况需要进行商品 ...
- 【C】Re01
一.GCC分步编译 xxx.c文件经历的一系列编译过程: #include <stdio.h> int main() { printf("Hello, World!\n" ...
- 国产深度学习框架 OneFlow 是否靠谱?
OneFlow框架的设计目标是实现:一个使用多机多卡就像使用单机单卡一样容易的深度学习框架. 可以说,这是国内最早的深度学习框架之一,也是至今还活着的公司中开发支持力度最低的,也是最缺少技术支持.用户 ...
- 根据baselines库修改的运行输入参数的解析代码
如题: def arg_parser(): """ Create an empty argparse.ArgumentParser. """ ...