我希望能干净地处理一个上下文,它可以在我的程序中被取消。我将建模它的 backbone 。
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
// tracks errors or successes
completionChannel := make(chan bool)
go func1(ctx)
go func2(ctx)
numberOfFunctions := 2
for i := 0; i < numberOfFunctions; i++ {
// async signal to know if channel was successful or not
result <- completionChannel
if !result {
// should cancel all further processing of the go routines initialized above
cancel()
return
}
}
completionChannel
用布尔值填充(假=失败,真=成功)- 如果从通道读取的值为假,则取消所有正在运行的go例程
func func1(ctx) {
retry := true
while (retry) {
// if context is cancelled, then terminate early (how do I do this elegantly?)
err := doThing()
if err.Status == 404 {
retry = false
}
}
}
想象一下func1
和func2
几乎是一样的。它们一遍又一遍地做一件事(想想指数回退)。我想阻止迭代继续,如果上下文被取消以防止内存泄漏。因为阅读一个没有被取消的通道是阻塞的,我该如何在注解所在的地方添加它呢?
编辑:
我可以只添加一个非阻塞选择吗?
select {
case <-ctx.Done():
fmt.Println("returning!")
return
default:
}
1条答案
按热度按时间fkaflof61#
看看这个
这里我修改了
doThing
函数,以便在状态失败时测试它我也使用了
sync.WaitGroup
来等待其他goroutine的结束要关闭所有其他goroutine,你还需要为它们提供
cancel
函数如果你需要跟踪状态,你可以简单地创建
completionChannel
,把所有的状态都推到那里(注意chan的长度(它将是length == routines count))。或者用slice把信息推到那里,在所有的goroutine退出后读取它。不要在附加信息的过程中读取它-- in可能会导致竞态条件我想是的