在带有select case和default的GOROUTIES中,一旦通道关闭,default将不会执行

在带有select case和default的GOROUTIES中,一旦通道关闭,default将不会执行,go,Go,我试图理解默认情况下select块中闭合通道的行为,但对以下输出感到困惑。 这里我调用50个goroutine并关闭finish通道 func testClosedChannelBehavior() { const n = 50 finish := make(chan bool) var done sync.WaitGroup for i := 0; i < n; i++ { done.Add(1) go func(x int

我试图理解默认情况下select块中闭合通道的行为,但对以下输出感到困惑。 这里我调用50个goroutine并关闭finish通道

func testClosedChannelBehavior() {
    const n = 50
    finish := make(chan bool)
    var done sync.WaitGroup
    for i := 0; i < n; i++ {
        done.Add(1)
        go func(x int) {
            select {
            case <-time.After(1 * time.Hour):
            case <-finish:
                fmt.Printf("received finish %d\n", x)
            default:
            fmt.Printf("I didnt wait %d\n", x)
            }
            done.Done()
        }(i)
    }
    t0 := time.Now()
    close(finish) 
    fmt.Println("finish closed")
    done.Wait() 
    fmt.Printf("Waited %v for %d goroutines to stop\n",     time.Since(t0), n)
}
func testClosedChannelBehavior(){
常数n=50
完成:=制作(陈波)
var done sync.WaitGroup
对于i:=0;i对fmt.Printf的case调用涉及一个syscall。Syscalls会自动导致该goroutine被重新调度,因为它必须等待操作系统完成该syscall。这意味着其中一些goroutine很可能运行select语句并选择默认的case,但还不能打印到控制台

编辑:此外,如果您在具有多个线程的系统上运行此程序,默认情况下,go运行时将并行运行多个go例程(与操作系统线程数匹配),这意味着其中一些goroutine可能与通道关闭同时执行,并在主goroutine中发生通道关闭之前到达select语句

如果您添加同步通道,以确保通道关闭操作在任何Goroutine中的
select
发生之前进行,则它将按预期工作:

func testClosedChannelBehavior(){
常数n=50
完成:=制作(陈波)
继续:=make(chan结构{})
var done sync.WaitGroup
对于i:=0;i对fmt.Printf的调用涉及一个syscall。Syscalls会自动导致该goroutine被重新调度,因为它必须等待操作系统完成该syscall。这意味着其中一些goroutine很可能运行select语句并选择默认情况,但还不能打印到控制台

编辑:此外,如果您在具有多个线程的系统上运行此程序,默认情况下,go运行时将并行运行多个go例程(与操作系统线程数匹配),这意味着其中一些goroutine可能与通道关闭同时执行,并在主goroutine中发生通道关闭之前到达select语句

如果您添加同步通道,以确保通道关闭操作在任何Goroutine中的
select
发生之前进行,则它将按预期工作:

func testClosedChannelBehavior(){
常数n=50
完成:=制作(陈波)
继续:=make(chan结构{})
var done sync.WaitGroup
对于i:=0;i感谢@Kaedys的快速响应。将接受此作为答案。同步通道是一个干净的修复:)…感谢@Kaedys的快速响应。将接受此作为答案。同步通道是一个干净的修复:)。。。
func testClosedChannelBehavior() {
    const n = 50
    finish := make(chan bool)
    proceed := make(chan struct{})
    var done sync.WaitGroup
    for i := 0; i < n; i++ {
        done.Add(1)
        go func(x int) {
            <-proceed
            select {
            case <-time.After(1 * time.Hour):
            case <-finish:
                fmt.Printf("received finish %d\n", x)
            default:
                fmt.Printf("I didnt wait %d\n", x)
            }
            done.Done()
        }(i)
    }
    t0 := time.Now()
    close(finish)
    fmt.Println("finish closed")
    close(proceed)
    done.Wait()
    fmt.Printf("Waited %v for %d goroutines to stop\n", time.Since(t0), n)
}