go - 按时选择。结果死锁后

标签 go channel

package main

import "time"

func main() {
    chan_never_used := make(chan int, 10)

    c := make(chan int, 10)
    for {
        select {
        case <-time.After(time.Second):
            c <- 0
        case c <- <-chan_never_used:
        }

        println(<-c)
    }
}

https://play.golang.org/p/7hZMdITecg

上面的代码导致fatal error: all goroutines are sleep - deadlock!

但是如果我改变一行:

package main

import "time"

func main() {
    chan_never_used := make(chan int, 10)

    c := make(chan int, 10)
    for {
        select {
        case <-time.After(time.Second):
            c <- 0
        case n := <-chan_never_used: // This line changed
            c <- n                   // Add this line
        }

        println(<-c)
    }
}

效果不错。

为什么第一个版本的代码会导致死锁,为什么这个改变能让代码工作?

最佳答案

按照标准 select statement包含一堆 SendReceive声明。

在本例中是发送语句。

发送语句定义为:

SendStmt = Channel "<-" Expression .
Channel  = Expression .

查看您的代码:

case c <- <-chan_never_used:

Channel分数是 c , Expression分数是 <-chan_never_used .

因此,select发送语句(可能)非阻塞的语义不适用,因为它是阻塞的表达式。在应用 Send Statements 语义之前,必须完全评估 Expression 部分。

关于go - 按时选择。结果死锁后,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43303406/

相关文章:

function - *(*uintptr) 和 **(**uintptr) 有什么区别

vue.js - 如何在Go Web服务器和Vue.js前端之间交换数据? http发布:404

go - 如何使用kubernetes apiserver获取CNI类型?

.net - WCF channel 故障状态是否有帮助?

dictionary - Golang 多个计时器与 map+channel+mutex

performance - golang 中的类型转换是如何工作的?

python - 戈朗 : swagger REST api documents generator

go - 为什么goroutine中的未缓冲 channel 获得了此顺序

go - 类型为 "set"的 channel

go - 当非默认是输入 channel 时,为什么 select in go 总是进入默认情况?