Go语言两种(超时退出)程序的对比

Go语言两种(超时退出)程序的对比

Go语言实现超时退出有好几种方式,比较常用的有两种:
① 使用定时器 time.After、time.timer 和 select 配合使用
② 使用 Context 包的 context.WithTimeout 方式实现

这两种方式还是有区别的,我比较喜欢使用 context.WithTimeout 的方式、一是比较优雅、二是 context 包是可重入的、比较适合复杂的业务场景

使用定时器 time.After、time.timer 和 select 配合实现超时退出

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
package main

import (
"fmt"
"time"
)

func main() {
done := make(chan bool) // 退出信号
timeout := time.Second * 5 // 设置超时时间

go func() {
// 模拟处理业务逻辑、并且任务超时
time.Sleep(time.Second * 10)
done <- true
close(done)
}()

// 监听多个通道的IO执行情况
select {
case <-done:
fmt.Println("Task finished...")
case <-time.After(timeout):
fmt.Println("Task timeout...")
}
}
1
Task timeout...

使用 Context 包的 context.WithTimeout 方式实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
package main

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

func main() {
timeout := time.Second * 5
ctx, cancel := context.WithTimeout(context.Background(), timeout)
defer cancel()

done := make(chan bool) // 任务完成信号

go func() {
// 模拟处理业务逻辑、并且任务超时
time.Sleep(time.Second * 2)
done <- true
close(done)
}()

select {
case <-done:
fmt.Println("Task finished...")
case <-ctx.Done():
fmt.Println("Task timeout...")
}
}
1
Task timeout...

总结


1.如果是实现简单的超时程序直接使用 time.After、time.timer 和 select 配合使用就可以、但是实际应用场景大多会是多个协程交互的完成业务,这个
时候使用 time.After 和 select 就比较难以实现复杂的业务场景.

2.Context包是go1.7提供的上下文,原生的并发控制原语;比较适合父协程和子协程和派出孙子协程的并发控制,尤其是超时控制直接就提供了context.WithTimeout 使用起来比较优雅,比较适合复杂的业务场景.