在Golang中实现“事件”(带通知器/接收器)的概念?

时间:2016-08-31 15:08:24

标签: multithreading go concurrency worker goroutine

我想知道在Golang中处理“事件”概念(带通知器/接收器)的正确方法是什么。我想我需要使用频道但不确定最佳方式。

具体来说,我在下面有两名工作人员。在某些条件下,“worker1”进入和退出“快速模式”并通过通道通知。然后“worker2”可以收到此事件。这很好,但两个工人紧密耦合。特别是,如果worker2没有运行,则worker1在写入通道时会等待等待。

Golang实现此逻辑的最佳方式是什么?基本上,一个工人做某事并通知任何其他工人它已经这样做了。其他工作人员是否听取此事件不得阻止worker1。理想情况下,可以有任意数量的工作人员可以听取此事件。

有什么建议吗?

var fastModeEnabled = make(chan bool)
var fastModeDisabled = make(chan bool)

func worker1() {
    mode := "normal"
    for {
        // under some conditions:
        mode := "fast"
        fastModeEnabled <- true

        // later, under different conditions:
        mode := "normal"
        fastModeDisabled <- true
    }
}

func worker2() {
    for {
        select {

        case <-fastModeEnabled:

            fmt.Println("Fast mode started")

        case <-fastModeDisabled:

            fmt.Println("Fast mode ended")

        }
    }
}

func main() {
    go worker2()
    go worker1()

    for {}
}

1 个答案:

答案 0 :(得分:3)

Use a non-blocking write to the channel. This way if anyone is listening they receive it. If there is no one listening it doesn't block the sender, although the event is lost.

You could use a buffered channel so that at least some events are buffered if you need that.

You implement a non-blocking send by using the select keyword with a default case. The default makes it non-blocking. Without the default case a select will block until one of its channels becomes usable.

Code snippit:

select {
    case ch <- event:
        sent = true
    default:
        sent = false
}