Goroutines слушают тот же результат на канале - PullRequest
0 голосов
/ 06 октября 2019

В настоящее время у меня есть несколько процедур одной и той же функции, которым нужно в какой-то момент ожидания их выполнения получить результат из отдельной части программы, прежде чем продолжить. Моими первыми мыслями было бы иметь канал для каждой из процедур, а затем, как только мы получим результат, мы перебираем все каналы, записываем в них и закрываем после?

Как мне «поделиться» результатом сэффективно / действенно? Является ли единственный способ записи в соответствующие каналы, которые они прослушивают / блокируют, прежде чем переходить к следующей части своего исполнения? Кажется немного чрезмерным.

Спасибо

Ответы [ 2 ]

2 голосов
/ 06 октября 2019

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

Вот пример. Функция printer представляет процедуры, ожидающие результата. Первый аргумент - это канал, который будет закрыт после установки результата. Второй аргумент - указатель на результат.

func printer(ready chan struct{}, result *string) {
    <-ready
    fmt.Println(*result)
}

Используйте его так:

ready := make(chan struct{})
var result string

// Start the goroutines.

go printer(ready, &result)
go printer(ready, &result)

// Set the result and close the channel to signal that the value is ready.

result = "Hello World!"
close(ready)

Это работает, потому что при получении на закрытом канале возвращается нулевое значение типа канала.

Запустите его на детской площадке

1 голос
/ 06 октября 2019

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

Примерно так:

var resultVar *ResultType // resultVar = nil means result not ready
var c sync.Cond // initialize this before using it

func f() {
  // compute result
  c.L.Lock()
  resultVar = result
  c.L.Unlock()
  c.Broadcast()
}

func goroutine() {
  ...
  c.L.Lock()
  for resultVar == nil {
    c.Wait()
  }
  c.L.Unlock()
}
...