暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

Context超时处理应该这么做

堆栈future 2022-12-19
365

超时处理应该这么做

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 %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(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 %s\n", 0, ctx.Err())
 }

复制


文章转载自堆栈future,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论