Go语言select中非阻塞写channel操作的行为疑问
Go无缓冲Channel在select中的发送行为解析
先看你给出的代码:
func main() { ch := make(chan int) select { case ch <- 42: fmt.Println("Sent value to channel") default: fmt.Println("Channel is not ready for sending") } select { case value := <-ch: fmt.Println("Received value from channel:", value) default: fmt.Println("Channel is not ready for receiving") } }
针对你的疑问:写操作ch <- 42从未被执行,直接触发了default分支,原因如下:
- 你创建的是无缓冲Channel(
make(chan int)默认无缓冲),这类Channel的发送规则是:必须有一个已准备好的接收goroutine,发送操作才能立即完成,否则当前goroutine会被阻塞。 - 这段代码里只有main一个goroutine,没有其他goroutine在等待接收
ch的值,所以ch <- 42这个操作无法立即完成。 - select语句的逻辑是:先检查所有case对应的操作是否能立即执行,如果没有任何case满足,就会执行default分支(如果存在的话)。这里发送操作无法立即完成,所以直接进入default,发送行为根本没发生。
补充验证:如果在select前启动一个goroutine负责接收,发送case就会被执行:
func main() { ch := make(chan int) // 启动一个goroutine等待接收 go func() { <-ch }() select { case ch <- 42: fmt.Println("Sent value to channel") default: fmt.Println("Channel is not ready for sending") } }
此时代码会打印Sent value to channel,因为有接收方准备好,发送操作可以立即完成。
回到原代码的第二个select,同样因为没有发送方准备好,接收操作无法立即完成,所以也会走default分支。
内容的提问来源于stack exchange,提问作者Ram Dittakavi
相关产品推荐
相关产品推荐

