超时处理应该这么做
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