1. 首页
  2. 主题
  3. Go问与答

请教 context.WithTimeout 的正确用法

nfwater · · 4170 次点击
如下这段代码: ``` package main import ( "context" "fmt" "sync" "time" ) var wg sync.WaitGroup func main() { ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second) defer cancel() wg.Add(2) go watch(ctx, 1) go watch(ctx, 2) wg.Wait() select { case <-ctx.Done(): fmt.Printf("watch %d %s\n", 0, ctx.Err()) } fmt.Println("finished") } func watch(ctx context.Context, flag int) { defer wg.Done() func() { fmt.Printf("doing something flag:%d\n", flag) time.Sleep(50 * time.Second) fmt.Println("finished flag:", flag) }() } ``` 在 main 里创建了一个 3s 超时的 ctx,并"捕获"完成信号,把 ctx 传到两个协程里,协程里 sleep 50s 来模拟工作,为什么到了 3s ,协程都还没有退出呢? 请教一下这个例子应该怎么改?谢谢!
```go package main import ( &#34;context&#34; &#34;fmt&#34; &#34;sync&#34; &#34;time&#34; ) var wg sync.WaitGroup func main() { ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second) defer cancel() go func() { wg.Add(2) go watch(ctx, 1) go watch(ctx, 2) wg.Wait() }() select { case &lt;-ctx.Done(): fmt.Printf(&#34;watch %d %s\n&#34;, 0, ctx.Err()) } fmt.Println(&#34;finished&#34;) } func watch(ctx context.Context, flag int) { defer wg.Done() func() { fmt.Printf(&#34;doing something flag:%d\n&#34;, flag) time.Sleep(50 * time.Second) fmt.Println(&#34;finished flag:&#34;, flag) }() } ``` * 以上改法就可以实现你说的退出 * 你的写法程序会在 wg.wait() 上停住,等待两个协程结束,所以你的写法不会出现超时退出的情况
#2
更多评论
这样是可以的,但感觉不像是标准用法 ``` package main import ( &#34;context&#34; &#34;fmt&#34; &#34;sync&#34; &#34;time&#34; ) var wg sync.WaitGroup // main 设置一个 3s 超时的 ctx,传给每个 goroutine 第一个参数,每个 goroutine 又发起协程处理任务, // 假设需要 5s,通过监听 ctx.Done 判断是否超时退出 func main() { ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second) defer cancel() wg.Add(2) go watch(ctx, 1) go watch(ctx, 2) wg.Wait() fmt.Println(&#34;finished&#34;) } func watch(ctx context.Context, flag int) { defer wg.Done() go func() { fmt.Printf(&#34;doing something flag:%d\n&#34;, flag) time.Sleep(50 * time.Second) fmt.Println(&#34;finished flag:&#34;, flag) }() select { case &lt;-ctx.Done(): fmt.Printf(&#34;watch %d %s\n&#34;, flag, ctx.Err()) return } } ```
#1

用户登录

没有账号?注册

今日阅读排行

    加载中

一周阅读排行

    加载中