• 掌握 Go 的计时器


    简介

    定时器是任何编程语言的重要工具,它允许开发人员在特定时间间隔安排任务或执行代码。在 Go 中,定时器是通过 time 包实现的,该包提供了一系列功能来创建、启动、停止和有效处理定时器。我们将探索 Go 中定时器的强大功能,并通过代码示例演示如何在应用程序中使用定时器。

    创建计时器

    要在 Go 中创建一个定时器,我们可以使用 time.NewTimer() 函数,该函数将持续时间作为参数。下面是一个示例:

    func CreateTimer() {
    	timer := time.NewTimer(2 * time.Second)
    	fmt.Println("Timer created.")
    
    	<-timer.C // 阻塞
    	fmt.Println("Timer expired.")
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    在上述代码片段中,我们使用 time.NewTimer() 创建了一个持续时间为 2 秒的新定时器。<-timer.C 语句会阻塞执行,直到定时器过期。定时器到期后,“Timer expired.”(定时器已过期)信息将打印到控制台。

    停止计时器

    在某些情况下,您可能想在定时器到期前停止它。为此,您可以使用定时器对象的 Stop() 方法。让我们修改之前的示例,加入定时器停止功能:

    func StopTimer() {
    	timer := time.NewTimer(2 * time.Second)
    	fmt.Println("Timer created.")
    
    	go func() {
    		<-timer.C
    		fmt.Println("Timer expired.")
    	}()
    
    	time.Sleep(1 * time.Second)
    	stopped := timer.Stop()
    	if stopped {
    		fmt.Println("Timer stopped.")
    	} else {
    		fmt.Println("Timer has already expired.")
    	}
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    在更新后的代码中,我们创建了一个 goroutine 来处理定时器过期,这样就可以在定时器过期前停止它。我们使用 time.Sleep() 函数来模拟在尝试停止计时器之前正在进行的一些工作。最后,我们调用 timer.Stop() 停止定时器。如果定时器已过期,timer.Stop() 返回 false,并打印 “定时器已过期”。否则,我们将打印 “定时器已停止”。

    重置计时器

    Go 还提供了重置活动定时器的方法。通过 Reset() 方法,您可以更改活动定时器的持续时间,重新开始倒计时。下面是一个示例:

    func ResetTimer() {
    	timer := time.NewTimer(10 * time.Second)
    	fmt.Printf("time: %d, Timer created.\n", time.Now().Unix())
    
    	time.Sleep(2 * time.Second)
    	reset := timer.Reset(3 * time.Second)
    	if reset {
    		fmt.Printf("time: %d, Timer reset.\n", time.Now().Unix())
    	} else {
    		fmt.Printf("time: %d, Timer has already expired.\n", time.Now().Unix())
    	}
    	<-timer.C // 阻塞
    	fmt.Printf("time: %d, Timer expired again.\n", time.Now().Unix())
    }
    
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    输出为:

    time: 1695183503, Timer created.
    time: 1695183505, Timer reset.
    time: 1695183508, Timer expired again.
    
    • 1
    • 2
    • 3

    在上述代码中,我们创建了一个持续时间为 10 秒的计时器。使用 time.Sleep() 等待 2 秒后,我们调用 timer.Reset(),新的持续时间为 3 秒。如果定时器尚未过期,则重置操作成功,我们将打印 “定时器重置”。否则,进入到 <-timer.C 阻塞阶段,然后打印 我们将打印 “Timer expired again.”。

    重置定时器与停止定时器

    了解重置定时器和使用 Stop() 停止定时器之间的区别非常重要。

    func CompareResetAndStop() {
    	timer := time.NewTimer(5 * time.Second)
    	fmt.Printf("time: %d, Timer created.\n", time.Now().Unix())
    
    	go func() {
    		<-timer.C
    		fmt.Printf("time: %d, Timer expired.\n", time.Now().Unix())
    	}()
    
    	time.Sleep(2 * time.Second)
    	timer.Reset(3 * time.Second)
    	fmt.Printf("time: %d, Timer reset.\n", time.Now().Unix())
    
    	time.Sleep(2 * time.Second)
    	timer.Stop()
    	fmt.Printf("time: %d, Timer stopped.\n", time.Now().Unix())
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    输出为:

    time: 1695183802, Timer created.
    time: 1695183804, Timer reset.
    time: 1695183806, Timer stopped.
    
    • 1
    • 2
    • 3

    在本例中,我们创建了一个持续时间为 5 秒的计时器。2 秒后,我们使用 timer.Reset() 将计时器重置为 3 秒。之后,再过 2 秒,我们使用 timer.Stop() 停止计时器。重置定时器会改变其持续时间并重新开始倒计时,而停止定时器则会立即停止执行,无论剩余持续时间多长。

    带 Ticker 的计时器

    Go 提供了一种 Ticker 类型,它是一种专门的定时器,可在指定的时间间隔内重复触发。定时器可用于定期执行任务。

    func Tick() {
    	ticker := time.NewTicker(1 * time.Second)
    	defer ticker.Stop()
    
    	go func() {
    		for range ticker.C {
    			fmt.Printf("time: %d, Ticker ticked!\n", time.Now().Unix())
    		}
    	}()
    
    	time.Sleep(5 * time.Second)
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    在本例中,我们使用 time.NewTicker() 创建了一个持续时间为 1 秒的 Ticker。然后,我们启动一个 goroutine,从 ticker.C channel 接收值,每当滴答声响起时,goroutine 就会发出一个值。在 goroutine 中,每次接收到一个 tick 时,我们都会打印 “Ticker ticked!”。调用 time.Sleep() 可以让滴答滴答运行 5 秒钟,然后退出程序。

    使用 Select 的超时

    Go 的 select 语句允许在多个通道上执行非阻塞操作。这可以用来使用计时器实现超时。

    func TimeOut() {
    	ch := make(chan string)
    
    	go func() {
    		time.Sleep(2 * time.Second)
    		ch <- "Operation completed."
    	}()
    
    	select {
    	case msg := <-ch:
    		fmt.Println(msg)
    	case <-time.After(1 * time.Second):
    		fmt.Println("Timeout reached.")
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    在本例中,我们创建了一个 channel ch,并启动一个 goroutine 来模拟耗时 2 秒的操作。我们使用 select 语句从 ch 接收信息,或使用 time.After() 等待超时。如果操作在 1 秒内完成,则打印消息。否则,将执行超时情况,并打印 “Timeout reached.”。

  • 相关阅读:
    Android小程序 java 产品合同管理系统python nodejs php客户资源管理系统
    JCL 学习
    C语言:文件操作(1)
    【云原生】-国产开源数据库openGauss容器部署
    kaggle使用深度学习的logistic回归方法实现疟疾细胞图像分类
    跨语言调用C#代码的新方式-DllExport
    swift枚举(三)-Optional
    【深度学习】常见开源框架介绍 || 主流深度学习框架 || Tensorflow || Pytorch
    计算机毕业设计(附源码)python舟影短视频平台
    MySQL数据库 主从复制与读写分离
  • 原文地址:https://blog.csdn.net/m0_73728511/article/details/133915739