关于匿名函数捕获迭代变量

本文探讨了Go语言中匿名函数对外部变量的引用问题,特别是在循环中可能导致的错误引用。通过示例展示了如何在for循环中创建匿名函数时,由于循环变量的地址相同,使得匿名函数可能操作的是同一个变量的引用。解决方案是通过创建局部变量来消除这种隐患。此外,还提到了类似问题可能出现在基于索引的for循环中。理解这一陷阱对于编写健壮的Go代码至关重要。
摘要由CSDN通过智能技术生成

        在GO语言匿名函数学习中我已经阐明了关于匿名函数对外层函数的变量的引用,在这里需要再次进行强调:匿名函数对外层变量的使用和修改是修改的外层变量的引用,由于在循环中变量的地址是相同的,导致匿名函数使用的变量可能会是同一个。

var rmdirs []func()
for _,d := range tempDirs() {
    dir := d                  // 注意,这一行是必须的
    os.MkdirAll(dir,0755)     // 也创建父目录
    rmdirs = append(rmdirs, func() {
        os.RemoveAll(dir)
    })
}

// ...这里做一些处理...
for _,rmdir := range rmdirs {
    rmdir() //清理
}

        可以看到第一个for循环中:dir := d,局部变量dir是循环变量d的一个副本,从而消除了rmdirs中是同一个变量引用的bug。

        风险不仅存在使用range的for循环中。下面的例子中也存在物件见的捕获的索引变量i而导致的同样的问题。

var rmdirs []func()
dirs := tempDirs()
for i := 0; i < len(dirs); i++ {
    os.MkdirAll(dirs[i], 0755) // ok
    rmdirs = append(rmdirs, func() {
        os.RemoveAll(dirs[i])  // 不正确
    })
}

        这两种捕获迭代变量导致的问题本质上是因为:在go语言中迭代变量使用同一个地址。

参考:《GO程序设计语言》

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值