注意:我使用谷歌搜索了这个主题,并阅读了我能找到的几乎所有内容,但仍然无法获得正确/合理/生产准备好的答案。
基本上所有答案都是相似的,就像这个答案一样:how to stop a groutine,所有答案都是相同的模式,没有例外:真正的作品是fmt.Println(1)
来打印某些内容,或者只是// Do other stuff
,
但如果将实际工作保持在for select default case branch
,那么它将被执行多次,以便打印好的东西,但很明显它还没有为实际工作做好准备。
我能想象的唯一有效方法是将实际工作放在案例分支上,然后将仅一个信号发送到该案例以通知它开始,例如:playground,但是只是感到烦恼,也有这种方法,它是否可能产生一些问题?
添加了代码片段以准确显示我想要实现的内容:https://play.golang.org/p/7xjjiW7XdoQ,我希望在客户端关闭连接时实现,然后立即终止我的处理程序,释放资源,并无条件退出。
答案 0 :(得分:0)
您想要在多个位置检查取消信号,而不是使用for select
循环。但是为了不阻止你仍然必须使用select
(空的默认情况)这使得它有点笨拙。我正在使用context.Context而不是“plain cancel 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")
}