Golang 闭包变量捕获分析

Golang closure variable capture analysis

Posted by alovn on March 24, 2022

变量捕获

Go语言中的变量捕获主要是用于处理闭包的,由于闭包中可能会引用到外部变量,所以对于捕获的变量需要明确在闭包中通过值或引用的方式进行传递。

示例

1
2
3
4
5
6
7
8
9
10
11
12
package main
import "fmt"
func main() {
  a := 1
  b := 2
  func(){
    for i:=0; i < 10; i++ {//若不加循环,可能会被内联优化
        fmt.Println(a, b)
    }
  }()
  a = 2
}

这个示例中的闭包中引入了闭包外的a、b变量,由于变量a在最后又进行了赋值操作,所以这里的闭包中a、b变量的引用方式会有所不同。对变量a会采用地址引用的方式,而对于变量b会直接使用值传递的方式。

我们可以直接通过Go提供的工具查看变量的捕获情况:

1
2
3
4
5
go tool compile -m=2 main.go | grep capturing

//Output
main.go:6:2: main capturing by ref: a (addr=false assign=true width=8)
main.go:7:2: main capturing by value: b (addr=false assign=false width=8)

从输出内容可以看出变量a采用了ref引用传递,而变量b采用了值传递。assign=true表示变量a在闭包完成后又进行了赋值操作。