首页 > 其他分享 >Go协程超时退出的三种方式

Go协程超时退出的三种方式

时间:2022-10-11 14:44:04浏览次数:63  
标签:WithTimeout 协程 After ctx context time Go 超时

主要介绍如何实现超时控制,主要有三种

1、context.WithTimeout/context.WithDeadline + time.After

2、context.WithTimeout/context.WithDeadline + time.NewTimer

3、channel + time.After/time.NewTimer

context.WithTimeout + time.After
func AsyncCall() {
ctx, cancel := context.WithTimeout(context.Background(), time.Duration(time.Millisecond*800))
defer cancel()

go func(ctx context.Context) {
// 发送HTTP请求
}()

select {
case <-ctx.Done():
fmt.Println("call successfully!!!")
return
case <-time.After(time.Duration(time.Millisecond * 900)):
fmt.Println("timeout!!!")
return
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
通过context的WithTimeout设置一个有效时间为800毫秒的context
该context会在耗尽800毫秒后或者方法执行完成后结束,结束的时候会向通道ctx.Done发送信号
Done通道负责监听context啥时候结束,如果在time.After设置的超时时间到了,你还没完事,那我就不等了,执行超时后的逻辑代码。
还要加上这个time.After呢?
这是因为该方法内的context是自己申明的,可以手动设置对应的超时时间,但是在大多数场景,这里的ctx是从上游一直传递过来的,对于上游传递过来的context还剩多少时间,我们是不知道的,所以这时候通过time.After设置一个自己预期的超时时间就很有必要了。
context.WithTimeout + time.NewTimer
func AsyncCall() {
ctx, cancel := context.WithTimeout(context.Background(), time.Duration(time.Millisecond * 800))
defer cancel()
timer := time.NewTimer(time.Duration(time.Millisecond * 900))

go func(ctx context.Context) {
// 发送HTTP请求
}()

select {
case <-ctx.Done():
timer.Stop()
timer.Reset(time.Second)
fmt.Println("call successfully!!!")
return
case <-timer.C:
fmt.Println("timeout!!!")
return
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
这里的主要区别是将time.After换成了time.NewTimer,也是同样的思路如果接口调用提前完成,则监听到Done信号,然后关闭定时器。否则的话,会在指定的timer即900毫秒后执行超时后的业务逻辑。
channel + time.After/time.NewTimer
func AsyncCall() {
ctx := context.Background()
done := make(chan struct{}, 1)

go func(ctx context.Context) {
// 发送HTTP请求
done <- struct{}{}
}()

select {
case <-done:
fmt.Println("call successfully!!!")
return
case <-time.After(time.Duration(800 * time.Millisecond)):
fmt.Println("timeout!!!")
return
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
这里主要利用通道可以在协程之间通信的特点,当调用成功后,向done通道发送信号。
监听Done信号,如果在time.After超时时间之前接收到,则正常返回,否则走向time.After的超时逻辑,执行超时逻辑代码。
这里使用的是通道和time.After组合,也可以使用通道和time.NewTimer组合。

剩下的盛夏~
关注

1


2


0

————————————————
版权声明:本文为CSDN博主「剩下的盛夏~」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/weixin_44879611/article/details/115537192

标签:WithTimeout,协程,After,ctx,context,time,Go,超时
From: https://www.cnblogs.com/ExMan/p/16779145.html

相关文章