Welcome toVigges Developer Community-Open, Learning,Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
3.5k views
in Technique[技术] by (71.8m points)

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
", s)
                os.Exit(0)
            default:
                time.Sleep(time.Second)
            }
        }
    }()

    for {
        fmt.Println("正在运行")
        time.Sleep(time.Second)
    }
}

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

有两种办法解决:

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

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

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


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to Vigges Developer Community for programmer and developer-Open, Learning and Share

2.1m questions

2.1m answers

63 comments

56.6k users

...