Golang or-channel的模式递归理解问题

关于Golang or-channle的模式,又多个协程并发,如果这些协程里面有一个结束,那么就是发出有关的消息,结束阻塞,相关的理解可以直接看代码。。我的问题在于:代码中向下递归的过程中,为什么还要添加本身的orDone这个chan interface(直接参照代码即可)。。这个模式来自《Concurrency programming with Go》书中的第四章的or-channel,希望有理解的同学可以解释一下,谢谢!!

package main

import (
    "fmt"
    "time"
)

func main() {
    // 从这里传入各个channel的done
    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{})  /// 这里是问题中提到的interface
        go func() {
            defer close(orDone) // 结束的时候释放本身的done信号
            switch len(channels) {
            case 2:
                select {
                case <-channels[0]:
                case <-channels[1]:
                }
            default:
                select {
                case <-channels[0]:
                case <-channels[1]:
                case <-channels[2]:
                // 问题在这里:为什么还要加入本身的orDone,这是我一直不明白的地方。。。
                case <-or(append(channels[3:], orDone)...): 
                }
            }
        }()
        return orDone
    }

    sig := func(after time.Duration) <-chan interface{} {
        c := make(chan interface{})  
        go func() {
            defer close(c) // 所在的goroutine结束后close,使用时间模拟工作时间
            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\n", time.Since(start))
}
/*
输出结果:
done after 1.000182106s
*/
阅读 3.1k
1 个回答
<-or(
        sig(1*time.Minute),
        sig(2*time.Minute),
        sig(3*time.Minute),
        sig(4*time.Minute),
    )

这样子的话 or 会被调用两次, 如果第二次不加入 orDone 的话, 第一次 channels[0] 1分钟后返回值, 第一个 or 调用结束, 但是第二个 or 调用此时还在阻塞状态中, 因为他还在等待 sig(3*time.Minute)sig(4*time.Minute).

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题