golang在有default的select语句中为何无法收到channel中传递的os.Signal?

新手上路,请多包涵
  • golang版本:1.15.3
  • os: Mac OS 10.15.7

在一个goroutine中使用for循环不断地检测一个os.Signal的channel,如果收到os.Interrupt或者os.Kill信号,则退出程序。如果没有,则执行select default中的语句。但当在终端中中止程序时,没有收到对应信号,无法停止。代码如下:

// 运行后会一直执行下去, 无法收到ch中的信号
func main() {
    ch := make(chan os.Signal)
    signal.Notify(ch, os.Interrupt, os.Kill)

    go func() {
        for {
            select {
            case s := <-ch:
                fmt.Printf("收到停止信号: %v\n", s)
                os.Exit(0)
            default:
                time.Sleep(time.Second)
            }
        }
    }()

    for {
        fmt.Println("正在运行")
        time.Sleep(time.Second)
    }
}
阅读 3.4k
1 个回答

有两种办法解决:

第一种:删除 default: time.Sleep(time.Second)

第二种:改用有缓冲通道 ch := make(chan os.Signal, 1)

无缓冲通道上的发送操作将会阻塞,直到另一个 goroutine 在对应的通道上执行接收操作。
缓冲通道上的接收操作在通道为空时会阻塞。
接收到信号时,由于select在执行default,ch不会收到信号。

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题