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语言超时退出内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Golang实现不被复制的结构体的方法

    Golang实现不被复制的结构体的方法

    sync包中的许多结构都是不允许拷贝的,因为它们自身存储了一些状态(比如等待者的数量),如果你尝试复制这些结构体,就会在你的 IDE中看到警告,那这是怎么实现的呢,下文就来和大家详细讲讲
    2023-03-03
  • Go语言中的Array、Slice、Map和Set使用详解

    Go语言中的Array、Slice、Map和Set使用详解

    这篇文章主要介绍了Go语言中的Array、Slice、Map和Set使用详解,本文给出了它们的创建、使用、多维等代码实例,需要的朋友可以参考下
    2014-10-10
  • 在Go语言中实现DDD领域驱动设计实例探究

    在Go语言中实现DDD领域驱动设计实例探究

    本文将详细探讨在Go项目中实现DDD的核心概念、实践方法和实例代码,包括定义领域模型、创建仓库、实现服务层和应用层,旨在提供一份全面的Go DDD实施指南
    2024-01-01
  • 基于Go+WebSocket实现实时通信功能

    基于Go+WebSocket实现实时通信功能

    在互联网应用程序中,实时通信是一种非常重要的功能,WebSocket 是一种基于 TCP 的协议,它允许客户端和服务器之间进行双向通信,本文将介绍如何使用 Golang 创建单独的 WebSocket 会话,以实现实时通信功能,需要的朋友可以参考下
    2023-10-10
  • 详解go-zero是如何做路由管理的

    详解go-zero是如何做路由管理的

    go-zero 是一个微服务框架,包含了 web 和 rpc 两大部分,而对于 web 框架来说,路由管理是必不可少的一部分,那么本文就来探讨一下 go-zero 的路由管理是怎么做的吧
    2023-08-08
  • Go打包二进制文件的实现

    Go打包二进制文件的实现

    这篇文章主要介绍了Go打包二进制文件的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-03-03
  • GO使用Mutex确保并发程序正确性详解

    GO使用Mutex确保并发程序正确性详解

    这篇文章主要为大家介绍了GO使用Mutex确保并发程序正确性详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-03-03
  • Go设计模式之迭代器模式讲解和代码示例

    Go设计模式之迭代器模式讲解和代码示例

    迭代器是一种行为设计模式, 让你能在不暴露复杂数据结构内部细节的情况下遍历其中所有的元素,本文将为大家详细介绍Go 迭代器模式,文中详细的代码示例,需要的朋友可以参考下
    2023-07-07
  • gorm FirstOrCreate和受影响的行数实例

    gorm FirstOrCreate和受影响的行数实例

    这篇文章主要介绍了gorm FirstOrCreate和受影响的行数实例,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2020-12-12
  • Golang基于Vault实现敏感信息保护

    Golang基于Vault实现敏感信息保护

    Vault 是一个强大的敏感信息管理工具,自带了多种认证引擎和密码引擎,本文主要探讨应用程序如何安全地从 Vault 获取敏感信息,并进一步实现自动轮转,感兴趣的可以了解一下
    2023-06-06

最新评论