猿问

尽管在这个通道上选择了一个 goroutine,为什么写通道被阻塞了?

我对以下代码感到困惑,我在代码中写下了一些注释,指出了我的困惑。并且在代码的最后有一个执行结果,我也写下了我期望的结果。


package main


import (

    "fmt"

    "time"

)


func sendRPC() bool {

    time.Sleep(5 * time.Second)

    return true

}


func main() {

    done := make(chan struct{})

    ch := make(chan bool)


    go func() { // goroutine A

        select {

        case ch <- sendRPC():

            fmt.Println("RPC return")

        case <-done:

            fmt.Println("exit")

        }

    }()


    select {

    case <-ch:

    case <-time.After(1000 * time.Millisecond):

        fmt.Println("timeout")

        if len(done) == 0 {

            fmt.Println("1")

            // here write done channel will block until sendRPC() return, why?

            // I expect that the write is nonblock because goroutine A is select on done channel.

            done <- struct{}{}

            fmt.Println("2")

        }

    }


    // result:

    // timeout (after about 1 second)

    // 1

    // exit    (after about 5 seconds, I expect that it is printed after about 1 second too.)

    // 2


}


白衣染霜花
浏览 96回答 1
1回答

繁星coding

规范说:对于语句中的所有情况,接收操作的通道操作数以及发送语句的通道和右侧表达式在输入“select”语句时按源顺序恰好计算一次。结果是一组要从中接收或发送到的通道,以及要发送的相应值。无论选择哪个(如果有的话)通信操作继续进行,该评估中的任何副作用都会发生。goroutine A 中选择的通道集等待对 的求值sendRPC()。查看这个等效的 goroutine 可能会有所帮助:go func() { // goroutine A    v := sendRPC()  // waits for 5 seconds    select {    case ch <- v:        fmt.Println("RPC return")    case <-done:        fmt.Println("exit")    }}()接收done延迟 5 秒。
随时随地看视频慕课网APP

相关分类

Go
我要回答