2016-08-16 5 views
1

У меня есть функция (а не замыкание), которая записывается на канал. Я вызове этой функции из goroutine вЧтение из параллельной функции через канал с использованием goroutine и замыкания, дающей ошибку

var wg sync.WaitGroup 
wg.Add(1) 
go DoStuff(somechan, &wg) 

Внутри DoStuff, у меня есть что-то вроде

for ; ; { 

    if err == io.EOF { 
     fmt.Println(err) 
     close(somechan) 
     fmt.Println("Closed channel") 
     break 
    } else if err != nil { 
     panic(err) 
    } 
    somechan <- Somefunc() 
} 

Теперь я пытаюсь читать с этого канала с помощью другого goroutine.

wgread.Add(1) 
go func() { 
    for ; ; { 
     select { 
     case chanoutput, ok := <-somechan: 
      if ok == true { 
       fmt.Println(string(*chanoutput)) 
      } else { 
       fmt.Println("DONE") 
       fmt.Println(ok) 
       wgread.Done() 
       break 
      } 
     } 

    } 
}() 
wgread.Wait() 

Однако, когда работает, я получаю

panic: sync: negative WaitGroup counter 

после печати

DONE 
false 
DONE 
false 

Если я дам wgread.Add (2), она будет печатать выше DONE и ложной 3 раз.

Почему возникает отрицательная ошибка счетчика waitgroup, хотя я увеличил дельта waitgroup на 1? Каков наилучший способ чтения из goroutine с использованием другой параллельной функции или закрытия?

+0

там не хватает вашего кода здесь, чтобы сообщить эту проблему. –

ответ

3

Оператор break вырывается из внутреннего большинства случаев, для оператора switch или switch. Функция, которая получает по somechan, вращается в цикле, уменьшая количество групп ожидания при закрытии канала. Написать такой код:

wgread.Add(1) 
go func() { 
    defer wgread.Done() 
    for chanoutput := range somechan { 
     fmt.Println(string(*chanoutput)) 
    } 
    fmt.Println("DONE") 
}() 
wgread.Wait() 

Если принимающий код, как написано в этом вопросе, то принимающий goroutine может устранен. Заменить код с wgread.Add(1) к wgread.Wait() с

for chanoutput := range somechan { 
    fmt.Println(string(*chanoutput)) 
} 
3

break не нарушает внешний цикл for. Для ссылки на внешний контур, вы можете использовать ярлык, как это:

Loop: 
    for { 
     select { 
      case ...: 
       break Loop 
     } 
    } 

Кроме того, чтобы помочь со стилем кодирования, вы должны практиковать с помощью gofmt для форматирования кода. Он, например, заменит for ; ; { ... } на очиститель for { ... }.

+0

Спасибо @Baloo, но с перерывом Loop главный поток ждет сейчас. – scott

 Смежные вопросы

  • Нет связанных вопросов^_^