Закрытие канала для передачи сигнала в движении

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

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

type BroadcastGroup struct {
    ch      chan interface{}
    msg     interface{}
}

func (bg *BroadcastGroup) Broadcast(msg interface{}) {
    bg.msg = msg
    close(bg.ch)
}

func (bg *BroadcastGroup) Wait() interface{} {
    <-bg.ch
    return bg.msg
}

func NewBroadcastGroup() *BroadcastGroup {
    bg := &BroadcastGroup{}
    bg.ch = make(chan interface{}, 0)
    return bg
}

person Jose Javier Gonzalez Ortiz    schedule 05.03.2018    source источник
comment
Можете ли вы привести пример того, как вы это используете, и какой вопрос по поводу его использования? Это просто похоже на упрощенное условное выражение, поскольку канал можно заменить мьютексом и выполнить то же самое.   -  person JimB    schedule 06.03.2018
comment
То же самое обсуждение: stackoverflow.com/questions /36417199/   -  person alexey_p    schedule 06.03.2018
comment
Это часть алгоритма консенсуса. Несколько клиентов могут ожидать фиксации одной и той же позиции индекса. Как только алгоритм решит, им всем нужно продолжить. Не могли бы вы уточнить решение мьютекса?   -  person Jose Javier Gonzalez Ortiz    schedule 06.03.2018
comment
Похоже, вам нужен sync.Cond.   -  person Adrian    schedule 06.03.2018
comment
@JoseJavierGonzalezOrtiz: я имею в виду только то, что здесь вы используете канал в качестве мьютекса, с той лишь разницей, что вы не можете повторно заблокировать его (что может быть хорошо, поскольку, если повторная трансляция недействительна, это будет удобно паниковать) . Хотя, если бы вы захотели сделать это повторно, вы, вероятно, в любом случае использовали бы sync.Cond. Без полного контекста мы не можем сказать, есть ли более простой шаблон, он и так довольно прост.   -  person JimB    schedule 06.03.2018
comment
Возможный дубликат Go: один производитель много потребителей   -  person Michael Hampton    schedule 06.03.2018
comment
Однажды я реализовал нечто подобное здесь, возможно, это поможет вам решить ваши мысли   -  person vardius    schedule 06.03.2018