使用goroutines时将函数调用包装到闭包中

时间:2015-05-31 21:49:12

标签: go closures goroutine

将函数调用包装到闭包中会导致使用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个工作人员。

闭包从外部作用域捕获变量的方式看起来有些不对劲。为什么会这样?闭包是否使用传递引用方式传递外部变量而不是传递值?

1 个答案:

答案 0 :(得分:2)

这就是所有语言中闭包的工作原理,如果你想这样做,你必须隔离变量。

go func(i int) { startWorker(i) }(i)