最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Go中的Timer 和 Ticker詳解

 更新時(shí)間:2024年07月05日 12:04:34   作者:百里守約學(xué)編程  
在日常開發(fā)中,我們可能會(huì)遇到需要延遲執(zhí)行或周期性地執(zhí)行一些任務(wù),這個(gè)時(shí)候就需要用到 Go 語言中的定時(shí)器,本文將會(huì)對這兩種定時(shí)器類型進(jìn)行介紹,感興趣的朋友一起看看吧

一:簡介

在日常開發(fā)中,我們可能會(huì)遇到需要延遲執(zhí)行或周期性地執(zhí)行一些任務(wù)。這個(gè)時(shí)候就需要用到 Go 語言中的定時(shí)器。

Go 語言中,定時(shí)器類型有兩種:一次性定時(shí)器time.Timer 和 周期性定時(shí)器time.Ticker 。本文將會(huì)對這兩種定時(shí)器類型進(jìn)行介紹。

二、Timer:一次性定時(shí)器

Timer 是一個(gè)一次性的定時(shí)器,用于在未來的某一時(shí)刻執(zhí)行一次操作。

基本使用
創(chuàng)建 Timer 定時(shí)器的方式有兩種:

  • NewTimer(d Duration) *Timer:該函數(shù)接受一個(gè) time.Duration 類型的參數(shù) d(時(shí)間間隔),表示定時(shí)器在過期(執(zhí)行之后過期)之前等待的時(shí)間。NewTimer 返回一個(gè)新的 Timer 定時(shí)器,這個(gè)定時(shí)器在其內(nèi)部維護(hù)一個(gè)通道 C,該通道在定時(shí)器被觸發(fā)時(shí)會(huì)接收當(dāng)前的時(shí)間值。
  • AfterFunc(d Duration, f func()) *Timer:接受一個(gè)指定的時(shí)間間隔 d 和回調(diào)函數(shù) f。該函數(shù)返回一個(gè)新的 Timer 定時(shí)器,在定時(shí)器到期時(shí)直接調(diào)用 f,而不是通過通道 C 發(fā)送信號。調(diào)用 TimerStop 方法可以停止定時(shí)器和取消調(diào)用 f

下面的代碼展示了如何使用 NewTimerAfterFunc 來創(chuàng)建定時(shí)器以及定時(shí)器的基本用法:

package main
import (
	"fmt"
	"time"
)
func main() {
	// 使用 NewTimer 創(chuàng)建一個(gè)定時(shí)器,1s后往timer.C中發(fā)送當(dāng)前時(shí)間
	timer := time.NewTimer(time.Second)
	gofunc() {
		select {
		case <-timer.C:
			fmt.Println("timer 定時(shí)器觸發(fā)啦!")
		}
	}()
	// 使用 AfterFunc 創(chuàng)建另一個(gè)定時(shí)器,1s后執(zhí)行func
	time.AfterFunc(time.Second, func() {
		fmt.Println("timer2 定時(shí)器觸發(fā)啦!")
	})
	// 主goroutine等待兩秒,確??吹蕉〞r(shí)器觸發(fā)的輸出
	time.Sleep(time.Second * 2)
}

代碼運(yùn)行結(jié)果如下所示:

timer 定時(shí)器觸發(fā)啦!
timer2 定時(shí)器觸發(fā)啦!

下面是代碼的逐步解析:

  • 首先使用 NewTimer 創(chuàng)建了一個(gè)定時(shí)器,然后在一個(gè)新的goroutine 中監(jiān)聽它的 C 屬性以等待定時(shí)器觸發(fā)。
  • 其次,使用 AfterFunc 創(chuàng)建另一個(gè)定時(shí)器,通過指定一個(gè) 回調(diào)函數(shù) 來處理定時(shí)器到期事件。
  • 最后,主 goroutine 等待足夠長的時(shí)間以確保定時(shí)器的觸發(fā)信息能夠被打印出來。

方法詳解

Reset
Reset(d Duration) bool:該方法用于重置 Timer 定時(shí)器的過期時(shí)間,也可以理解為重新激活定時(shí)器。它接受一個(gè) time.Duration 類型的參數(shù) d,表示定時(shí)器在過期之前等待的時(shí)間。

除此之外,該方法還返回一個(gè) bool 值:

  • 如果定時(shí)器處于活動(dòng)的狀態(tài),返回 true。
  • 如果定時(shí)器已經(jīng)過期或被停止了,返回 falsefalse 并不意味著激活定時(shí)器失敗,只是標(biāo)識定時(shí)器的當(dāng)前狀態(tài))。

下面是代碼示例:

package main
import (
	"fmt"
	"time"
)
func main() {
	timer := time.NewTimer(5 * time.Second)
	// 第一次重置,定時(shí)器處于激活狀態(tài),因此返回 true
	b := timer.Reset(1 * time.Second)
	fmt.Println(b) // true
	second := time.Now().Second()
	select {
	case t := <-timer.C:
		fmt.Println(t.Second() - second) // 1s
	}
	// 第二次重置,定時(shí)器已經(jīng)處于過期狀態(tài),因此返回 false
	b = timer.Reset(2 * time.Second)
	fmt.Println(b) // false
	second = time.Now().Second()
	select {
	case t := <-timer.C:
		fmt.Println(t.Second() - second) // 2s
	}
}

代碼運(yùn)行結(jié)果如下所示:

true
1    
false
2

下面是代碼的逐步解析:

  • 首先,創(chuàng)建了一個(gè)定時(shí)器,設(shè)置為 5 秒后到期。
  • 然后調(diào)用 Reset 方法立即將其重置為 1 秒后到期。因?yàn)榇藭r(shí)定時(shí)器仍處于激活狀態(tài)(即還未到期),所以Reset方法返回 true。
  • 接下來的 select 語句等待定時(shí)器到期,并打印出實(shí)際經(jīng)過的秒數(shù)(約等于 1 秒)。
  • 接著第二次重置定時(shí)器,這次設(shè)置為 2 秒后到期。由于定時(shí)器在這次重置時(shí)已經(jīng)到期,Reset 方法返回 false。
  • 最后,再次使用 select 語句等待定時(shí)器到期,并打印出這次經(jīng)過的秒數(shù)(約等于 2 秒)。

Stop

Stop() bool:該方法用于停止定時(shí)器。如果定時(shí)器停止成功,返回 true,如果定時(shí)器已經(jīng)過期或被已經(jīng)被停止過,則返回 false。切記:Stop 操作不會(huì)關(guān)閉通道 C。這意味著無論是通過 for select 還是 for range 去監(jiān)聽 ticker.C,我們需要使用其他機(jī)制來退出循環(huán),例如使用 context 上下文。下面是代碼示例:

package main
import (
	"fmt"
	"time"
)
func main() {
	timer := time.NewTimer(3 * time.Second)
	// 停止定時(shí)器,在定時(shí)器觸發(fā)之前停止它,因此返回 true
	stop := timer.Stop()
	fmt.Println(stop) // true
	stop = timer.Stop()
	// 第二次停止定時(shí)器,此時(shí)定時(shí)器已經(jīng)被停止了,返回 false
	fmt.Println(stop) // false
}

代碼運(yùn)行結(jié)果如下所示:

true
false

下面是代碼的逐步解析:

  • 首先,創(chuàng)建了一個(gè)設(shè)置為3秒后觸發(fā)的定時(shí)器。
  • 然后立即調(diào)用Stop方法停止定時(shí)器。因?yàn)榇藭r(shí)定時(shí)器還未觸發(fā),所以Stop返回 true。
  • 最后再次調(diào)用Stop 方法嘗試停止同一個(gè)定時(shí)器。由于定時(shí)器已經(jīng)被停止,這次 Stop 返回 false。

三:Ticker:周期性定時(shí)器

Tciker 是一個(gè)周期性的定時(shí)器,用于在固定的時(shí)間間隔重復(fù)執(zhí)行任務(wù)。它在每個(gè)間隔時(shí)間到來時(shí),向其通道(Channel)發(fā)送當(dāng)前時(shí)間。

基本使用
我們可以使用 NewTicker 函數(shù)來創(chuàng)建一個(gè)新的 Ticker 對象,該函數(shù)接受一個(gè) time.Duration 類型的參數(shù) d(時(shí)間間隔)。

下面是代碼示例:

package main
import (
	"context"
	"fmt"
	"time"
)
func main() {
	// 每隔1秒往ticker.C中發(fā)送當(dāng)前時(shí)間
	ticker := time.NewTicker(time.Second)
	defer ticker.Stop()
	// 使用context控制下面的for select退出
	timeout, cancelFunc := context.WithTimeout(context.Background(), time.Second*5)
	defer cancelFunc()
	go func() {
		for {
			select {
			case <-timeout.Done():
				fmt.Println("timeout done")
				return
			case <-ticker.C:
				fmt.Println("定時(shí)器觸發(fā)啦!")
			}
		}
	}()
	// 主goroutine等待 7 秒,確??吹蕉〞r(shí)器觸發(fā)的輸出
	time.Sleep(time.Second * 7)
}

代碼運(yùn)行結(jié)果如下所示:

定時(shí)器觸發(fā)啦!
定時(shí)器觸發(fā)啦!
定時(shí)器觸發(fā)啦!
定時(shí)器觸發(fā)啦!
定時(shí)器觸發(fā)啦!
timeout done

下面是代碼的逐步解析:

  • 首先,創(chuàng)建了一個(gè)每秒觸發(fā)的定時(shí)器,確保函數(shù)周期結(jié)束后清理定時(shí)器,我們應(yīng)該加上 defer ticker.Stop()
  • 然后,創(chuàng)建一個(gè)在 5 秒后超時(shí)的上下文。cancelFunc 被用于在退出前清理上下文。
  • 接著,在一個(gè)新的 goroutine 中,select 語句用于監(jiān)聽兩個(gè)通道:定時(shí)器的通道 (ticker.C) 和超時(shí)上下文的完成通道 (timeout.Done())。當(dāng)定時(shí)器每秒觸發(fā)時(shí),會(huì)打印出消息。當(dāng)上下文超時(shí)(即 5 秒過后),打印出超時(shí)信息,并返回,從而結(jié)束該 goroutine
  • 最后,主 goroutine 通過time.Sleep(time.Second * 7)等待 7 秒,以確保能夠觀察到定時(shí)器觸發(fā)和超時(shí)事件的輸出。

除了使用 select 語句監(jiān)聽 ticker.C 以外,我們還可以使用 for range 的形式進(jìn)行監(jiān)聽:

for range ticker.C {}

需要注意的是,即使通過 Stop 方法停止 Ticker 定時(shí)器,其 C 通道不會(huì)被關(guān)閉。這意味著無論是通過 for select 還是 for range 去監(jiān)聽 ticker.C,我們需要使用其他機(jī)制來退出循環(huán),例如使用 context 上下文。

方法詳解

Reset
Reset(d Duration) 方法用于停止計(jì)時(shí)器并將其周期重置為指定的時(shí)間。下一個(gè)時(shí)間刻度將在新周期結(jié)束后生效。它接受一個(gè) time.Duration 類型的參數(shù) d,表示新的周期。該參數(shù)必須大于零;否則 Reset 方法內(nèi)部將會(huì) panic

下面是代碼示例:

package main
import (
	"time"
)
func main() {
	ticker := time.NewTicker(5 * time.Second)
	defer ticker.Stop()
	// 重置定時(shí)器
	ticker.Reset(1 * time.Second)
	second := time.Now().Second()
	for t := range ticker.C {
		// 1s
		fmt.Printf("周期:%d 秒", t.Second()-second)
		break
	}
}

代碼運(yùn)行結(jié)果如下所示:

周期:1 秒

下面是代碼的逐步解析:

  • 首先,創(chuàng)建了一個(gè)每 5 秒觸發(fā)一次的定時(shí)器 time.Ticker
  • 其次,使用 Reset 方法重置定時(shí)器的觸發(fā)間隔。5 秒變成 1 秒。
  • 最后,通過一次循環(huán),打印定時(shí)器的周期,預(yù)期結(jié)果為 1 秒。

Stop
Stop() 方法用于停止定時(shí)器。在 Stop 之后,將不再發(fā)送更多的 tick 給其通道 C。切記:Stop 操作不會(huì)關(guān)閉通道 C。

下面是代碼示例:

package main
import (
	"fmt"
	"time"
)
func main() {
	ticker := time.NewTicker(time.Second)
	quit := make(chanstruct{}) // 創(chuàng)建一個(gè)退出通道
	go func() {
		for {
			select {
			// ticker Stop后,不會(huì)往ticker.C中發(fā)送當(dāng)前時(shí)間了,并且ticker.C并沒有關(guān)閉,所以Stop后,不會(huì)再走該case了
			case <-ticker.C:
				fmt.Println("定時(shí)器觸發(fā)啦!")
			// 關(guān)閉的chan是可以讀的,讀完chan中已有數(shù)據(jù)后,可以一直讀出對應(yīng)類型的零值,所以一旦quit被close,quit立馬可讀
			case <-quit:
				fmt.Println("協(xié)程停止啦!")
				return// 接收到退出信號,退出循環(huán)
			}
		}
	}()
	time.Sleep(time.Second * 3)
	ticker.Stop() // 停止定時(shí)器
	close(quit)   // 發(fā)送退出信號
	fmt.Println("定時(shí)器停止啦!")
}

代碼運(yùn)行結(jié)果如下所示:

定時(shí)器觸發(fā)啦!
定時(shí)器觸發(fā)啦!
定時(shí)器觸發(fā)啦!
協(xié)程停止啦!
定時(shí)器停止啦!

  • 首先,創(chuàng)建一個(gè)每秒觸發(fā)一次的 time.Ticker 對象。同時(shí),引入了一個(gè)類型為 chan struct{} 的退出通道 quit。這個(gè)通道將用于向運(yùn)行中的 goroutine 發(fā)送停止信號。
  • 其次,啟動(dòng)一個(gè)新的 goroutine。在這個(gè) goroutine 中,使用for-select循環(huán)來監(jiān)聽兩個(gè)事件:定時(shí)器的觸發(fā)(case <-ticker.C)和退出信號(case <-quit)。每當(dāng)定時(shí)器觸發(fā)時(shí),它會(huì)打印一條消息。如果收到退出信號,它會(huì)打印一條消息并退出循環(huán)。
  • 接著,在主goroutine中,time.Sleep(time.Second * 3) 模擬了一段等待時(shí)間(3 秒),在這期間定時(shí)器會(huì)觸發(fā)幾次。
  • 最后,主 goroutine 通過調(diào)用 Stop 方法停止定時(shí)器,然后關(guān)閉退出通道。goroutine 接收到退出信號后打印出一條消息并退出循環(huán)。

Stop 不會(huì)關(guān)閉其通道 C,因此我們需要借助其他方式(例如退出信號)來清理資源。

四:Timer 和 Ticker 的主要區(qū)別

用途:

  • Timer 用于單次延遲執(zhí)行任務(wù)。
  • Ticker 重復(fù)執(zhí)行任務(wù)。

行為特點(diǎn):

  • Timer 在設(shè)定的延遲時(shí)間過后觸發(fā)一次,發(fā)送一個(gè)時(shí)間值到其通道。
  • Ticker 按照設(shè)定的間隔周期性地觸發(fā),反復(fù)發(fā)送時(shí)間值到其通道。

可控性:

  • Timer 可以被重置(Reset 方法)和停止(Stop 方法)。
  • Reset 用于改變 Timer 的觸發(fā)時(shí)間。
  • Ticker 可以被重置(Reset 方法)和停止(Stop 方法)。
  • Reset 用于改變 Ticker 觸發(fā)的時(shí)間間隔。

結(jié)束操作:

  • TimerStop 方法用于阻止Timer觸發(fā),如果 Timer 已經(jīng)觸發(fā),Stop 不會(huì)從其通道中刪除已發(fā)送的時(shí)間值。
  • TickerStop方法用于停止 Ticker 的周期性觸發(fā),一旦停止,它不會(huì)再向通道發(fā)送新的值。

注意事項(xiàng)

  • 無論是 Timer 還是Ticker定時(shí)器,調(diào)用 Stop 方法之后,并不會(huì)關(guān)閉它們的 C 通道。如果有其他的 goroutine 在監(jiān)聽這個(gè)通道,為避免潛在的內(nèi)存泄漏,需要手動(dòng)結(jié)束該 goroutine。通常,這種資源釋放的問題可以通過使用 context 或通過關(guān)閉信號(利用 Channel 實(shí)現(xiàn))來解決。
  • 當(dāng)Ticker定時(shí)器完成其任務(wù)后,為了防止內(nèi)存泄漏,應(yīng)調(diào)用 Stop 方法來釋放相關(guān)資源。如果未及時(shí)停止 Ticker,可能導(dǎo)致資源持續(xù)占用。
  • 在編寫 Go 代碼時(shí),我們應(yīng)根據(jù)不同的應(yīng)用場景去選擇合適的定時(shí)器。同時(shí),我們應(yīng)遵循良好的規(guī)范,特別是在定時(shí)器使用完畢后及時(shí)釋放資源,對于避免潛在的內(nèi)存泄漏問題尤為重要。

到此這篇關(guān)于Go中的Timer 和 Ticker的文章就介紹到這了,更多相關(guān)Go Timer 和 Ticker內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • GO語言實(shí)現(xiàn)AES-CFB加密的操作方法

    GO語言實(shí)現(xiàn)AES-CFB加密的操作方法

    本文介紹了如何用Go語言實(shí)現(xiàn)AES-CFB加密和解密,首先,定義一個(gè)屬于encrypt包的文件,使用AES算法、CFB模式和Base64編碼等功能,在加密函數(shù)中,接收明文和密鑰,生成一個(gè)AES塊密碼和一個(gè)隨機(jī)的初始化向量,實(shí)現(xiàn)明文的加密
    2024-10-10
  • GoFrame基于性能測試得知grpool使用場景

    GoFrame基于性能測試得知grpool使用場景

    這篇文章主要為大家介紹了GoFrame基于性能測試得知grpool使用場景示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-06-06
  • go打包aar及flutter調(diào)用aar流程詳解

    go打包aar及flutter調(diào)用aar流程詳解

    這篇文章主要為大家介紹了go打包aar及flutter調(diào)用aar流程詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-03-03
  • Golang使用etcd構(gòu)建分布式鎖的示例分享

    Golang使用etcd構(gòu)建分布式鎖的示例分享

    在本教程中,我們將學(xué)習(xí)如何使用Go和etcd構(gòu)建分布式鎖系統(tǒng),分布式鎖系統(tǒng)對于管理對分布式系統(tǒng)中共享資源的并發(fā)訪問至關(guān)重要,它有助于維護(hù)一致性,防止競爭條件,并確保在任何給定時(shí)間只有一個(gè)進(jìn)程獨(dú)占訪問資源,需要的朋友可以參考下
    2025-01-01
  • Go語言RPC Authorization進(jìn)行簡單ip安全驗(yàn)證的方法

    Go語言RPC Authorization進(jìn)行簡單ip安全驗(yàn)證的方法

    這篇文章主要介紹了Go語言RPC Authorization進(jìn)行簡單ip安全驗(yàn)證的方法,實(shí)例分析了Go語言進(jìn)行ip驗(yàn)證的技巧,需要的朋友可以參考下
    2015-03-03
  • Go語言變量的聲明實(shí)現(xiàn)示例

    Go語言變量的聲明實(shí)現(xiàn)示例

    本文主要介紹了Go語言變量的聲明實(shí)現(xiàn)示例,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2024-03-03
  • GO語言embed機(jī)制的使用

    GO語言embed機(jī)制的使用

    本文詳細(xì)介紹了Go語言中使用embed機(jī)制將靜態(tài)文件(如圖片、文本和目錄)嵌入到程序中,包括文件轉(zhuǎn)[]byte、string類型,以及使用FS結(jié)構(gòu)組合多個(gè)文件和目錄的方法,下面就來詳細(xì)的介紹一下
    2026-03-03
  • Go語言基礎(chǔ)數(shù)組用法及示例詳解

    Go語言基礎(chǔ)數(shù)組用法及示例詳解

    這篇文章主要為大家介紹了Go語言基礎(chǔ)Go語言數(shù)組的用法及示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2021-11-11
  • Go?strings包處理字符串的完整指南

    Go?strings包處理字符串的完整指南

    在?Go?語言開發(fā)中,字符串處理幾乎無處不在,Go?標(biāo)準(zhǔn)庫中的?strings?包提供了一整套?高效、簡單、常用的字符串處理函數(shù),下面小編就和大家詳細(xì)介紹一下它的具體使用吧
    2026-03-03
  • Go互斥鎖和讀寫鎖完整代碼舉例

    Go互斥鎖和讀寫鎖完整代碼舉例

    讀寫鎖(sync.RWMutex)與互斥鎖(sync.Mutex)是Go語言中兩種最核心的并發(fā)控制機(jī)制,本質(zhì)區(qū)別在于對讀操作的并發(fā)支持,這篇文章主要介紹了Go互斥鎖和讀寫鎖的相關(guān)資料,需要的朋友可以參考下
    2026-06-06

最新評論

乌海市| 闽清县| 沅江市| 观塘区| 略阳县| 客服| 宁乡县| 张掖市| 安新县| 景谷| 洛川县| 乐东| 安宁市| 仁怀市| 新建县| 前郭尔| 云阳县| 祁东县| 荃湾区| 来凤县| 苗栗市| 沾益县| 宁河县| 岳阳市| 肇源县| 沈阳市| 弥勒县| 中西区| 涿鹿县| 木兰县| 冷水江市| 瑞金市| 丘北县| 灵武市| 襄樊市| 德保县| 湄潭县| 牟定县| 康定县| 丹巴县| 永兴县|