栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Go语言

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

Go语言 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

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
		 }
}
  • 通过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
 	}
}
  • 这里的主要区别是将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
 	}
}
  • 这里主要利用通道可以在协程之间通信的特点,当调用成功后,向done通道发送信号。
  • 监听Done信号,如果在time.After超时时间之前接收到,则正常返回,否则走向time.After的超时逻辑,执行超时逻辑代码。
  • 这里使用的是通道和time.After组合,也可以使用通道和time.NewTimer组合。
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/908415.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号