首页 > 解决方案 > 为什么通道阻塞时select语句会抛出错误

问题描述

在此示例中,通道已满,因此 select 语句中的第一个 case 将阻塞,从而导致打印 default case。或者至少那是我认为应该发生的事情。相反,我收到错误“所有 goroutines 都在睡觉 - 死锁!”。为什么是这样?我认为 select 语句会阻塞,直到其中一种情况可以运行,这是本示例中的默认情况。

 func main() {
        c := make(chan int)
        c <- 1
    
        select {
            case c <- 5:
                fmt.Println("a")
            default:
                fmt.Println("only case not blocked")
            // fatal error: all goroutines are asleep - deadlock!
    }
    }

标签: go

解决方案


通道是为 goroutine 通信而设计的。当一个通道已满时,发送者等待另一个 goroutine 接收它。

无缓冲的通道总是满的:必须有另一个 goroutine 来接收发送者发送的内容(同时)。

在这一部分中,您将写入一个频道:

c <- 1

这个也写入无缓冲通道,这会阻止它:

case c <- 5:

这个例子基于你的代码来展示它是如何工作的:

package main

import (
    "fmt"
    "time"
)

func main() {
    c := make(chan int)
    go func() {
        fmt.Println(<-c) // starting goroutine and continuously reading from chan "c"
    }()

    time.Sleep(time.Millisecond) //to let goroutine start before program ends

    select {
    case c <- 5: // write into the channel so goroutine can read
        fmt.Println("a")
    default:
        fmt.Println("only case not blocked")
    }
    time.Sleep(time.Millisecond) //to let goroutine start before program finishes
}

推荐阅读