Go语言超时退出的三种实现方式总结

Laila ·
更新时间:2024-04-29
· 673 次阅读

目录

1、Go语言三种方式实现超时退出

1.1 context.WithTimeout/context.WithDeadline + time.After

1.2 context.WithTimeout/context.WithDeadline + time.NewTimer

1.3 channel + time.After/time.NewTimer

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 go语言

需要 登录 后方可回复, 如果你还没有账号请 注册新账号