Concurrency In Go 002 or-channel模式

作者:guoxj
浏览:363

    有时候,你可能发现你想要将多个 done channel 合并成一个单一的 done channel 来在这个符合 done channel 中的任意一个 channel 关闭的时候关闭整个 done channel。
    编写一个执行这种耦合的选择语句是完全可以接受的,尽管很冗长。
    但是,有时你无法知道你在运行时使用的 done channel 的数量,在这种情况下,或者你只喜欢单线程,你可以使用 or-channel 模式将这些 channel 组合在一起。
var or func(channels ...<-chan interface{}) <-chan interface{}
or = func(channels ...<-chan interface{}) <-chan interface{} {
    switch len(channels) {
    case 0:
        return nil
    case 1:
        return channels[0]
    }

    orDone := make(chan interface{})
    go func() {
        defer close(orDone)
        switch len(channels) {
        case 2:
            select {
            case <-channels[0]:
            case <-channels[1]:
            }
        default:
            select {
            case <-channels[0]:
            case <-channels[1]:
            case <-channels[2]:
            //  很有意思的递归,实现了一个 channel 关闭程序,
            case <-or(append(channels[3:], orDone)...):
            }
        }
    }()
    return orDone
}

sig := func(after time.Duration) <-chan interface{} {
    c := make(chan interface{})
    go func() {
        defer close(c)
        time.Sleep(after)
    }()
    return c
}
start := time.Now()
<-or(
    sig(2*time.Hour),
    sig(5*time.Minute),
    sig(1*time.Second),
    sig(1*time.Hour),
    sig(1*time.Minute),
)
fmt.Printf("done after %v", time.Since(start))

 




登录后回复

共有0条评论