Go语言超时退出的三种实现方式总结
更新时间:2023年06月18日 09:38:35 作者:242030
这篇文章主要为大家详细介绍了Go语言中超时退出的三种实现方式,文中的示例代码简洁易懂,对我们深入了解Go语言有一定的帮助,需要的可以了解一下
1、Go语言三种方式实现超时退出
1.1 context.WithTimeout/context.WithDeadline + time.After
// time.After(time.Duration(time.Millisecond * 700))
package main
import (
"context"
"fmt"
"time"
)
// Golang三种方式实现超时退出-方法1
// 场景:设定一个超时时间,若是在指定超时时间后没有返回结果,则重试
func main() {
// 经过context的WithTimeout设置一个有效时间为800毫秒的context
// 该context会在耗尽800毫秒后或者方法执行完成后结束,结束的时候会向通道ctx.Done发送信号
ctx, cancel := context.WithTimeout(context.Background(), time.Duration(time.Millisecond*800))
// 注意,这里要记得调用cancel(),否则即便提早执行完了,还要傻傻等到800毫秒后context才会被释放
defer cancel()
go func(ctx context.Context) {
// 发送HTTP请求
fmt.Println("处理请求!")
time.Sleep(800 * time.Millisecond)
fmt.Println("请求处理完毕!")
}(ctx)
select {
case <-ctx.Done():
fmt.Println("call successfully!!!")
return
// 这里已经设置了context的有效时间,为何还要加上这个time.After呢
// 这是由于该方法内的context是本身声明的,能够手动设置对应的超时时间,可是在大多数场景,这里的ctx是从上游一直传递过来的,
// 对于上游传递过来的context还剩多少时间,咱们是不知道的,因此这时候经过time.After设置一个本身预期的超时时间就颇有必要了
case <-time.After(time.Duration(time.Millisecond * 700)):
fmt.Println("timeout!!!")
return
}
}程序输出
处理请求!
timeout!!!
修改超时时间:
// time.After(time.Duration(time.Millisecond * 1000))
package main
import (
"context"
"fmt"
"time"
)
// Golang三种方式实现超时退出-方法1
// 场景:设定一个超时时间,若是在指定超时时间后没有返回结果,则重试
func main() {
// 经过context的WithTimeout设置一个有效时间为800毫秒的context
// 该context会在耗尽800毫秒后或者方法执行完成后结束,结束的时候会向通道ctx.Done发送信号
ctx, cancel := context.WithTimeout(context.Background(), time.Duration(time.Millisecond*800))
// 注意,这里要记得调用cancel(),否则即便提早执行完了,还要傻傻等到800毫秒后context才会被释放
defer cancel()
go func(ctx context.Context) {
// 发送HTTP请求
fmt.Println("处理请求!")
time.Sleep(800 * time.Millisecond)
fmt.Println("请求处理完毕!")
}(ctx)
select {
case <-ctx.Done():
fmt.Println("call successfully!!!")
return
// 这里已经设置了context的有效时间,为何还要加上这个time.After呢
// 这是由于该方法内的context是本身申明的,能够手动设置对应的超时时间,可是在大多数场景,这里的ctx是从上游一直传递过来的,
// 对于上游传递过来的context还剩多少时间,咱们是不知道的,因此这时候经过time.After设置一个本身预期的超时时间就颇有必要了
case <-time.After(time.Duration(time.Millisecond * 1000)):
fmt.Println("timeout!!!")
return
}
}程序输出
处理请求!
请求处理完毕!
call successfully!!!
1.2 context.WithTimeout/context.WithDeadline + time.NewTimer
// time.NewTimer(time.Duration(time.Millisecond * 700))
package main
import (
"context"
"fmt"
"time"
)
// Golang三种方式实现超时退出-方法2
// 使用time.NewTimer
func main() {
ctx, cancel := context.WithTimeout(context.Background(), time.Duration(time.Millisecond*800))
defer cancel()
timer := time.NewTimer(time.Duration(time.Millisecond * 700))
go func(ctx context.Context) {
// 发送HTTP请求
fmt.Println("处理请求!")
time.Sleep(800 * time.Millisecond)
fmt.Println("请求处理完毕!")
}(ctx)
select {
case <-ctx.Done():
timer.Stop()
timer.Reset(time.Second)
fmt.Println("call successfully!!!")
return
case <-timer.C:
fmt.Println("timeout!!!")
return
}
}程序输出
处理请求!
timeout!!!
修改超时间:
// time.NewTimer(time.Duration(time.Millisecond * 1000))
package main
import (
"context"
"fmt"
"time"
)
// Golang三种方式实现超时退出-方法2
// 使用time.NewTimer
func main() {
ctx, cancel := context.WithTimeout(context.Background(), time.Duration(time.Millisecond*800))
defer cancel()
timer := time.NewTimer(time.Duration(time.Millisecond * 1000))
go func(ctx context.Context) {
// 发送HTTP请求
fmt.Println("处理请求!")
time.Sleep(800 * time.Millisecond)
fmt.Println("请求处理完毕!")
}(ctx)
select {
case <-ctx.Done():
timer.Stop()
timer.Reset(time.Second)
fmt.Println("call successfully!!!")
return
case <-timer.C:
fmt.Println("timeout!!!")
return
}
}程序输出
处理请求!
请求处理完毕!
call successfully!!!
1.3 channel + time.After/time.NewTimer
// time.After(time.Duration(700 * time.Millisecond))
package main
import (
"context"
"fmt"
"time"
)
// Golang三种方式实现超时退出-方法3
// 使用通道
func main() {
ctx := context.Background()
done := make(chan struct{}, 1)
go func(ctx context.Context) {
// 发送HTTP请求
fmt.Println("处理请求!")
time.Sleep(800 * time.Millisecond)
fmt.Println("请求处理完毕!")
done <- struct{}{}
}(ctx)
select {
case <-done:
fmt.Println("call successfully!!!")
return
case <-time.After(time.Duration(700 * time.Millisecond)):
fmt.Println("timeout!!!")
return
}
}程序输出
处理请求!
timeout!!!
修改超时时间:
// time.After(time.Duration(1000 * time.Millisecond))
package main
import (
"context"
"fmt"
"time"
)
// Golang三种方式实现超时退出-方法3
// 使用通道
func main() {
ctx := context.Background()
done := make(chan struct{}, 1)
go func(ctx context.Context) {
// 发送HTTP请求
fmt.Println("处理请求!")
time.Sleep(800 * time.Millisecond)
fmt.Println("请求处理完毕!")
done <- struct{}{}
}(ctx)
select {
case <-done:
fmt.Println("call successfully!!!")
return
case <-time.After(time.Duration(1000 * time.Millisecond)):
fmt.Println("timeout!!!")
return
}
}程序输出
处理请求!
请求处理完毕!
call successfully!!!
到此这篇关于Go语言超时退出的三种实现方式总结的文章就介绍到这了,更多相关Go语言超时退出内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!
相关文章
Go语言中strings.HasPrefix、strings.Split、strings.SplitN() 函数
本文主要介绍了Go语言中strings.HasPrefix、strings.Split、strings.SplitN()函数,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧2024-08-08
Go语言入门教程之Arrays、Slices、Maps、Range操作简明总结
这篇文章主要介绍了Go语言入门教程之Arrays、Slices、Maps、Range操作简明总结,本文直接给出操作代码,同时对代码加上了详细注释,需要的朋友可以参考下2014-11-11


最新评论