The problem of pattern Recursive understanding of Golang or-channel

with regard to the mode of Golang or-channle, multiple cooperators are concurrent. If there is an end in one of these protocols, it is to send out the relevant message and end the blocking. The relevant understanding can be directly viewed from the code. My question is: in the process of downward recursion in the code, why add its own orDone chan interface (directly to the code). No, no, no. This pattern comes from or-channel, in the fourth chapter of the book "Concurrency programming with Go". I hope students who understand can explain it. Thank you!

package main

import (
    "fmt"
    "time"
)

func main() {
    // channeldone
    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) // goroutineclose
            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
*/
May.11,2021

<-or(
        sig(1*time.Minute),
        sig(2*time.Minute),
        sig(3*time.Minute),
        sig(4*time.Minute),
    )

in this case, or will be called twice. If orDone is not added the first channels [0] 1 minute later, the first or call ends, but the second or call is still blocked because he is still waiting for sig (3*time.Minute) and sig (4*time.Minute) .

Menu