微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

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

目录

1.context.WithTimeout + time.After

2.context.WithTimeout + time.NewTimer

3.channel + time.After/time.NewTimer


1.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设置一个自己预期的超时时间就很有必要了。

2.context.WithTimeout + time.NewTimer

func AsyncCall() {
 	ctx,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毫秒后执行超时后的业务逻辑。

3.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组合。
 

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐