//当协程里某一个方法执行超时后,我们需要退出协程,不能让它一直执行,并且返回超时的的消息
//网上大部分都是错误的
//我们自己的业务函数应该去返回一个channel
func Job() chan bool {
cha := make(chan bool)
//我们的逻辑部分,必须要用协程,这样 case <-Job(): 才能取到值,
//如果没有用协程,case <-Job()根本就取不到值,那么就是死锁
go func() {
//执行我们的操作
time.Sleep(time.Second * 3)
cha <- true
}()
//返回chan,外部去取,如果没有取到,代表我们的任务还没执行完毕
return cha
}
func main() {
//参数1需要传递一个根context,这里用Background即可
//这里设置的是当前时间后2秒还没执行完,那就是超时
//这里为了规范,在程序结束后取消所有协程,所以调用了defer cancel()
ctx, cancel := context.WithDeadline(context.Background(),
time.Now().Add(time.Second*2))
defer cancel()
wait := sync.WaitGroup{}
wait.Add(1)
go func() {
defer wait.Done()
//注意这里没有加for循环,因为我们的任务只需要执行一次
select {
case <-ctx.Done():
fmt.Println("超时了")
//网上很多在这个位置使用了 time.after, 扯淡的
//正确的应该是在这里调用我们自己的业务函数
case <-Job():
fmt.Println("我的任务完成")
}
}()
//阻塞程序
wait.Wait()
//如果返回了错误,则输出错误
err := ctx.Err()
if err != nil {
//输出context deadline exceeded
fmt.Println(err.Error())
}
}