go - 从孩子取消上下文
问题描述
我对 Golang 比较陌生,正在尝试将 Contexts 合并到我的代码中。
我看到了从父级取消以及共享特定于上下文的内容(例如记录器)方面的好处。
除此之外,我可能会遗漏一些东西,但我看不到孩子取消上下文的方法。此处的示例是,如果其中一个子例程遇到错误,则意味着整个上下文已完成。
这是一些示例代码:
package main
import (
"context"
"fmt"
"math/rand"
"os"
"os/signal"
"sync"
"time"
)
func main() {
ctx, cancel := context.WithCancel(context.Background())
// handle SIGINT (control+c)
go func() {
c := make(chan os.Signal, 1)
signal.Notify(c, os.Interrupt)
<-c
fmt.Println("main: interrupt received. cancelling context.")
cancel()
}()
wg := sync.WaitGroup{}
wg.Add(1)
go func() {
child1DoWork(ctx)
wg.Done()
}()
wg.Add(1)
go func() {
child2DoWork(ctx)
wg.Done()
}()
fmt.Println("main: waiting for children to finish")
wg.Wait()
fmt.Println("main: children done. exiting.")
}
func child1DoWork(ctx context.Context) {
// pretend we're doing something useful
tck := time.NewTicker(5 * time.Second)
for {
select {
case <-tck.C:
fmt.Println("child1: still working")
case <-ctx.Done():
// context cancelled
fmt.Println("child1: context cancelled")
return
}
}
}
func child2DoWork(ctx context.Context) {
// pretend we're doing something useful
tck := time.NewTicker(2 * time.Second)
for {
select {
case <-tck.C:
if rand.Intn(5) < 4 {
fmt.Println("child2: did some work")
} else {
// pretend we encountered an error
fmt.Println("child2: error encountered. need to cancel but how do I do it?!?")
// PLACEHOLDER: HOW TO CANCEL FROM HERE?
return
}
case <-ctx.Done():
// context cancelled
fmt.Println("child2: context cancelled")
return
}
}
}
在这里,您有一个从父级取消的示例(由于 SIGINT),效果很好。但是,在 child2DoWork 中有一个占位符遇到错误,然后我想取消整个上下文,但是我看不到使用 vanilla 上下文功能的方法。
这超出了上下文的范围吗?显然,我可以从 child2 与父母沟通,然后可以取消,但我想知道是否没有更简单的方法。
如果与父母沟通是正确的方式,是否有一种惯用的方式来做到这一点?这似乎是一个普遍的问题。
谢谢!
解决方案
孩子不能也不应该取消上下文,这是父母的电话。孩子可以做的是返回一个错误,父母应该决定这个错误是否需要取消上下文。
仅仅因为“子任务”失败,并不意味着所有其他子任务都需要取消。通常,失败的子任务可能意味着其他子任务变得更加重要。想想并行搜索:您可以使用多个子任务在多个来源中搜索相同的东西。您可以使用最快的结果并可能希望取消较慢的结果。如果搜索失败,您确实希望其余的继续。
显然,如果你将取消函数传递给孩子,孩子将有权取消上下文。而是将这种权力留给父母。
推荐阅读
- sapui5 - 如何从外部访问组件模型
- ruby - Slim:方法调用中的注释语法
- scsi - 物理驱动器上 SCSI 读取 (10) 的最大传输大小
- javascript - yup.js 条件时检查数组
- azure - 为什么从 Azure Key Vault 获取证书需要将其存储为机密?
- c - 开关盒不影响变量 C
- sql-server - Azure 数据工作室:另存为 CSV
- google-sheets - GSheets - 如何查询部分字符串
- javascript - 如何在 Actions on Google 意图实现 V2 中调用 2 个或更多异步方法
- c# - 与 ntdll.dll 相关的无法解释的崩溃