Context超时处理应该这么做

超时处理应该这么做

1、超时处理有问题代码

只通过select监听超时信号,没有处理正常逻辑处理。

package main

import (
 "context"
 "fmt"
 "sync"
 "time"
)

var wg sync.WaitGroup

func main() {
 // 定义一个3s超时context 所有衍生出来的goroutine必须在3s内完成 否则会cancel掉
 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()
 }()

// 这里有问题,因为不管是超时还是未超时都会进入<-ctx.Done() 也就是都会等待3s 这不是我们想要的
 select {
 case <-ctx.Done():
  fmt.Printf("watch %d %sn", 0, ctx.Err())
 }

 fmt.Println("finished")
}

func watch(ctx context.Context, flag int) {
 defer wg.Done()

 func() {
  fmt.Printf("doing something flag:%dn", flag)
  time.Sleep(10*time.Second)
  fmt.Println("finished flag:", flag)
 }()
}

2、如何解决?

很简单,就是在所有goroutine结束之后发送一个done信号给主goroutine,这样select就会监听到这个信号,从而安全退出。

// 增加done信号
 done := make(chan struct{})
 go func() {
  wg.Add(2)
  go watch(ctx, 1)
  go watch(ctx, 2)
  wg.Wait()
  done <- struct{}{} // 发送done信号
 }()

 select {
 case <-done: // 接受done信号
  fmt.Println("Done")
 case <-ctx.Done():
  fmt.Printf("watch %d %sn", 0, ctx.Err())
 }


原文始发于微信公众号(堆栈future):Context超时处理应该这么做

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/103420.html

(0)
小半的头像小半

相关推荐

发表回复

登录后才能评论
极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!