go - 如何使用 channel 通知 goroutine 正确退出

标签 go

注意:我用谷歌搜索了这个主题,并阅读了我能找到的几乎所有内容,但仍然无法获得正确/合理/生产就绪的答案。

基本上所有答案都差不多,就像这个:how to stop a groutine , 都采用相同的模式,无一异常(exception):真正的工作是 fmt.Println(1)打印一些东西,或者只是// Do other stuff ,

但如果将实际工作保留在 for select default case branch , 然后它将被执行多次,用于打印一些东西它很好,但显然它还没有为实际工作做好准备。

我能想到的唯一有效方法是将真正的工作放在一个案例分支上,然后向该案例发送仅一个信号以通知它开始,就像这里:playground ,但只是觉得苦恼,同样使用这种方法,它是否会产生一些潜在的问题?

添加代码片段以准确显示我想要实现的目标:https://play.golang.org/p/7xjjiW7XdoQ ,我想实现当客户端关闭连接时,立即终止我的处理程序,释放资源,并无条件退出。

最佳答案

您不想使用 for select 循环,而是要在多个地方检查取消信号。但是为了不阻塞,您仍然必须使用 select (默认大小写为空),这有点尴尬。我使用的是 context.Context 而不是“普通取消 channel ”,但想法是一样的:

func doWork(ctx context.Context) {
    fmt.Println("Doing some work 1")
    time.Sleep(time.Second * 5)
    // check is the task cancelled
    select {
    case <-ctx.Done():
        fmt.Println("cancelled at checkpoint 1")
        return
    default:
    }
    fmt.Println("Doing some work 2")
    time.Sleep(time.Second * 5)
    // check is the task cancelled
    select {
    case <-ctx.Done():
        fmt.Println("cancelled at checkpoint 2")
        return
    default:
    }
    fmt.Println("Doing some work 3")
    time.Sleep(time.Second * 5)
}

func main() {
    var wg sync.WaitGroup
    wg.Add(1)
    ctx, cancel := context.WithTimeout(context.Background(), time.Second*10)
    defer cancel()
    go func() {
        doWork(ctx)
        wg.Done()
    }()
    wg.Wait()
    fmt.Println("done")
}

关于go - 如何使用 channel 通知 goroutine 正确退出,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50489557/

相关文章:

go - filepath.Walk() - 我可以提供关于哪些目录不能行走的规则吗?

ubuntu - Shell命令如何执行以及它们在什么上下文中运行?

go - 处理程序中的变量未传递给模板

go - 如何捕获像 ctrl+c 这样的 os 信号并通过 gorilla websocket 在 go 中发送它们

go - 如何将图像转换为 pdf 文档 go lang?

sockets - UDP SetWriteBuffer 和 SetReadBuffer 如何处理操作系统的缓冲区?

go - 我如何检查我是否与 mqtt 代理失去联系?

go - 服务器未从 GO 中的 TCP 客户端接收数据

go - 为什么我的 golang 无锁队列总是卡在那里?

random - Go中如何生成固定长度的随机数?