2015-05-31 1 views
-1

Обтекание вызова функции в закрытие приводит к неожиданному поведению при использовании goroutines.Объединение вызова функции в закрытие при использовании 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) Into func() { startWorker(i) }() результаты вызова только 5-й рабочий.

Похоже, что что-то не так в том, как замыкания захватывают переменные из внешнего пространства. Почему это происходит? Затворы используют метод pass-by-reference для передачи внешних переменных вместо передачи по значению?

ответ

3

Вот как работают замыкания на всех языках, если вы хотите сделать это таким образом, вам нужно изолировать переменную.

go func(i int) { startWorker(i) }(i) 
Смежные вопросы