登录
首页 >  Golang >  Go问答

Go通道为何会阻塞而不退出

来源:stackoverflow

时间:2024-02-14 12:27:23 465浏览 收藏

积累知识,胜过积蓄金银!毕竟在Golang开发的过程中,会遇到各种各样的问题,往往都是一些细节知识点还没有掌握好而导致的,因此基础知识点的积累是很重要的。下面本文《Go通道为何会阻塞而不退出》,就带大家讲解一下知识点,若是你对本文感兴趣,或者是想搞懂其中某个知识点,就请你继续往下看吧~

问题内容

我有这两个版本来使用 signal.notifycontext 实现信号上下文取消

版本 1 https://play.golang.org/p/rwonyegpece

func main() {
    ch := run()
    <-ch
}

func run() chan bool {
    ctx, stop := signal.notifycontext(context.background(), os.interrupt, syscall.sigterm, syscall.sigquit)
    var done = make(chan bool)

    //go func() {
    select {
    case <-ctx.done():
        fmt.println("quitting")
        stop()
        done <- true
    }
    //}()
    return done
}

版本 2 https://play.golang.org/p/oijbicesrnt

func main() {
    ch := run()
    <-ch
}

func run() chan bool {
    ctx, stop := signal.NotifyContext(context.Background(), os.Interrupt, syscall.SIGTERM, syscall.SIGQUIT)
    var done = make(chan bool)

    go func() {
       select {
       case <-ctx.Done():
          fmt.Println("Quitting")
          stop()
          done <- true
       }
    }()
    return done
}

为什么第一个版本打印 quitting 行但不退出,而第二个版本打印并正常退出?


正确答案


第一种情况的行为不符合您的预期的原因是因为所有内容都在单个(主)goroutine 中运行。

select {
   case <-ctx.Done():
      fmt.Println("Quitting")
      stop()
      done <- true  // this blocks because no one is listening
   }
}

在第二个示例中,因为上述逻辑在 goroutine 中运行,所以 main() 将在通道上监听。

首选第二种方法,因为任何信号处理程序(在程序的生命周期内运行)都应该在其自己的 goroutine 中运行。

到这里,我们也就讲完了《Go通道为何会阻塞而不退出》的内容了。个人认为,基础知识的学习和巩固,是为了更好的将其运用到项目中,欢迎关注golang学习网公众号,带你了解更多关于的知识点!

声明:本文转载于:stackoverflow 如有侵犯,请联系study_golang@163.com删除
相关阅读
更多>
最新阅读
更多>
课程推荐
更多>