go闭包和普通函数调用的区别

432 阅读1分钟

看下面两段代码:

代码片段1:
package main

import (
    "fmt"
)

func main() {
    a := []int{1, 2, 3}
    for _, value := range a {
        fmt.Println(value)
        defer p(value)
    }
}
 
func p(value int) {
    fmt.Println(value)
}

执行结果

1
2
3
3
2
1

代码片段2:
package main

import (
    "fmt"
)

func main() {
    a := []int{1, 2, 3}
    for _, value := range a {
        fmt.Println(value)
        defer func() {
            fmt.Println(value)
        }()
    }
}

执行结果

1
2
3
3
3
3
  • 在Go的for…range循环中,Go始终使用值拷贝的方式代替被遍历的元素本身,简单来说,就是for…range中那个value,是一个值拷贝,而不是元素本身。也是说value是个局部变量,只是把元素赋值给该变量而已。

  • 闭包里的非传递参数外部变量值是传引用的(非常重要),也就是闭包是地址引用。在闭包函数里那个value就是外部非闭包函数自己的参数,所以是相当于引用了外部的变量

  • 有了以上两点的理解,再来理解代码2的结果就容易多了。闭包是通过地址引用来引用环境中的变量value,因此每次只是把value的地址拷贝了一份儿,就这样拷贝了三次。而执行到最后时value值为3,所以打印了3次value地址指向的值,所以是3,3,3。

参考:www.cnblogs.com/ralap7/p/91…