需求:
- 任务可以手动触发
- 任务可以自动触发
- 任务可以正常执行完毕结束
- 任务可以被手动中止
- 任务可以在超过指定时间后自动结束(超时机制)
不费话,上代码:
package main
import (
"context"
"log"
"time"
)
func main() {
var autoTimeout = 8
ctx, timeout := context.WithTimeout(context.Background(), time.Duration(autoTimeout) * time.Second)
go watch(ctx,"【监控】")
// 下面这个manual比autoTimeout大,就会让watch走自动超时,如果比autoTimeout小,就会调超时函数(也就是手动触发了超时让子goroutine结束)
var manual = 10
time.Sleep(time.Duration(manual) * time.Second)
log.Println("可以了,通知监控停止")
timeout()
log.Println("main等待") // 这里是手动触发了timeout之后,等待一下看看结果,测试性质的代码
time.Sleep(2 * time.Second)
log.Println("main结束")
}
func watch(ctx context.Context, name string) {
defer func() {
log.Println(name, "监控子goroutine返回")
}()
ch := make(chan int)
done := make(chan int)
go func() {
for i := 0; i < 5; i++ {
time.Sleep(time.Second)
ch <- i
}
done <- 1
}()
for true {
select {
case n := <- ch:
log.Println(name, "goroutine任务执行中...", n)
case n := <- done:
log.Println(name, "goroutine正常完成...", n)
return
case <-ctx.Done():
log.Println(name, "监控中止:", ctx.Err())
return
}
}
}
实际使用时,可以将上述任务相关的东西封装到一个struct中就可以实现抽象和内聚了,上述代码亲测覆盖所有需求没问题,分享给大家。