将函数调用包装到闭包中会导致使用goroutines时出现意外行为。
考虑以下示例:
package main
import (
"log"
"sync"
"time"
)
var workerNum = 5
var wg sync.WaitGroup
func block() {
dur := 300 * time.Millisecond
//time.Sleep()
select {
case <- time.After(dur): {}
}
}
func startWorker(worker int) {
for i:=0; i < 3; i++{
log.Printf("Worker %d woke up! \n", worker)
block()
}
wg.Done()
}
func main() {
for i:=0; i < workerNum; i++ {
//go func() { startWorker(i) }()
go startWorker(i)
}
wg.Add(workerNum)
wg.Wait()
}
在此测试:http://play.golang.org/p/nMlnTkbwVf
可以看到将startWorker(i)
包裹到func() { startWorker(i) }()
会导致只调用第5个工作人员。
闭包从外部作用域捕获变量的方式看起来有些不对劲。为什么会这样?闭包是否使用传递引用方式传递外部变量而不是传递值?
答案 0 :(得分:2)
这就是所有语言中闭包的工作原理,如果你想这样做,你必须隔离变量。
go func(i int) { startWorker(i) }(i)