亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

Go語言中的定時器原理與實戰(zhàn)應用

 更新時間:2024年10月14日 09:26:35   作者:景天科技苑  
在Go語言中,Timer和Ticker是處理定時任務的重要工具,Timer用于一次性事件,而Ticker則用于周期性事件,本文詳細介紹了這兩種定時器的創(chuàng)建、使用和停止方法,并通過實際案例展示了它們在監(jiān)控日志、檢查系統(tǒng)狀態(tài)等方面的應用

在Go語言中,定時器是并發(fā)編程中常用的工具之一。定時器可以用于監(jiān)控某個goroutine的運行時間、定時打印日志、周期性執(zhí)行任務等多種場景。
Go標準庫提供了兩種主要的定時器:Timer(一次性定時器)和Ticker(周期性定時器)。本文將詳細介紹這兩種定時器的用法,并通過實際案例展示其應用場景。

一、Timer定時器

Timer定時器是一種一次性定時器,即在未來某個時刻觸發(fā)的事件只會執(zhí)行一次。
Timer的結構中包含一個Time類型的管道C,主要用于事件通知。
在未到達設定時間時,管道內(nèi)沒有數(shù)據(jù)寫入,一直處于阻塞狀態(tài);到達設定時間后,會向管道內(nèi)寫入一個系統(tǒng)時間,觸發(fā)事件。

1. 創(chuàng)建Timer

使用time.NewTimer函數(shù)可以創(chuàng)建一個Timer定時器。該函數(shù)接受一個Duration類型的參數(shù),表示定時器的超時時間,并返回一個*Timer類型的指針。
看下源碼,Timer結構體中,timer.C是一個時間類型的通道

在這里插入圖片描述

package main

import (
    "fmt"
    "time"
)

func main() {
    // func NewTimer(d Duration) *Timer
    timer := time.NewTimer(2 * time.Second) // 設置超時時間2秒
    // 先打印下當前時間
    fmt.Println("當前時間:", time.Now())

    //我們可以打印下這個只讀通道的值
        //timer.C就是我們在定義定時器的時候,存放的時間,等待對應的時間。現(xiàn)在這個就是根據(jù)當前時間加2秒

    fmt.Println("通道里面的值", <-timer.C)
}

可以看到timer.C這個只讀通道里面的值,就是通過NewTimer設置時間間隔后的時間

在這里插入圖片描述

因此,我們可以根據(jù)時間通道,來定時將來某個時間要做的事

package main

import (
    "fmt"
    "time"
)

func main() {
    timer := time.NewTimer(2 * time.Second) // 設置超時時間2秒
    <-timer.C
    //經(jīng)過兩秒后只想下面代碼
    fmt.Println("after 2s Time out!")
}

在這里插入圖片描述

在上述代碼中,創(chuàng)建了一個超時時間為2秒的定時器,程序會阻塞在<-timer.C處,直到2秒后定時器觸發(fā),程序繼續(xù)執(zhí)行并打印“after 2s Time out!”。

2. 停止Timer

使用Stop方法可以停止一個Timer定時器。該方法返回一個布爾值,表示定時器是否在超時前被停止。
如果返回true,表示定時器在超時前被成功停止;如果返回false,表示定時器已經(jīng)超時或已經(jīng)被停止過。

在這里插入圖片描述

package main

import (
    "fmt"
    "time"
)

func main() {
    timer := time.NewTimer(2 * time.Second) // 設置超時時間2秒
    //這里,創(chuàng)建定時器后,里面執(zhí)行了停止方法,肯定是在定時器超時前停止了,返回true
    res := timer.Stop()
    fmt.Println(res) // 輸出:true
}

在上述代碼中,創(chuàng)建了一個超時時間為2秒的定時器,并立即調(diào)用Stop方法停止它。由于定時器還沒有超時,所以Stop方法返回true。

3. 重置Timer

對于已經(jīng)過期或者是已經(jīng)停止的Timer,可以通過Reset方法重新激活它,并設置新的超時時間。Reset方法也返回一個布爾值,表示定時器是否在重置前已經(jīng)停止或過期。

在這里插入圖片描述

package main

import (
    "fmt"
    "time"
)

func main() {
    timer := time.NewTimer(2 * time.Second)
    <-timer.C
    fmt.Println("time out1")
    //經(jīng)過兩秒后,定時器超時了
    res1 := timer.Stop()
    //此時再stop,得到的是false
    fmt.Printf("res1 is %t\n", res1) // 輸出:false
    //然后我們重置定時器。重置成3秒后超時
    timer.Reset(3 * time.Second)
    res2 := timer.Stop()
    //此時再stop,由于定時器沒超時,得到的是true
    fmt.Printf("res2 is %t\n", res2) // 輸出:true
}

在這里插入圖片描述

在上述代碼中,首先創(chuàng)建了一個超時時間為2秒的定時器,并在超時后打印“time out1”。
然后調(diào)用Stop方法停止定時器,由于定時器已經(jīng)過期,所以Stop方法返回false。
接著調(diào)用Reset方法將定時器重新激活,并設置新的超時時間為3秒。
最后再次調(diào)用Stop方法停止定時器,由于此時定時器還沒有過期,所以Stop方法返回true。

4. time.AfterFunc

time.AfterFunc函數(shù)可以接受一個Duration類型的參數(shù)和一個函數(shù)f,返回一個*Timer類型的指針。在創(chuàng)建Timer之后,等待一段時間d,然后執(zhí)行函數(shù)f。

package main

import (
    "fmt"
    "time"
)

func main() {
    duration := time.Duration(1) * time.Second
    f := func() {
        fmt.Println("f has been called after 1s by time.AfterFunc")
    }
    // func AfterFunc(d Duration, f func()) *Timer
    //等待duration時間后,執(zhí)行f函數(shù)
    //這里是經(jīng)過1秒后。執(zhí)行f函數(shù)
    timer := time.AfterFunc(duration, f)
    defer timer.Stop()
    time.Sleep(2 * time.Second)
}

在上述代碼中,創(chuàng)建了一個超時時間為1秒的定時器,并在超時后執(zhí)行函數(shù)f。
使用defer語句確保在程序結束時停止定時器。程序會在1秒后打印“f has been called after 1s by time.AfterFunc”。

5. time.After

time.After函數(shù)會返回一個*Timer類型的管道,該管道會在經(jīng)過指定時間段d后寫入數(shù)據(jù)。調(diào)用這個函數(shù)相當于實現(xiàn)了一個定時器。

在這里插入圖片描述

package main

import (
    "fmt"
    "time"
)

func main() {
    ch := make(chan string)
    go func() {
        time.Sleep(3 * time.Second)
        ch <- "test"
    }()
    
    //使用select,哪個先到來,耗時時間短,執(zhí)行哪個
    select {
    case val := <-ch:
        fmt.Printf("val is %s\n", val)
    // 這個case是兩秒后執(zhí)行
    // func After(d Duration) <-chan Time
    case <-time.After(2 * time.Second):
        fmt.Println("timeout!!!")
    }
}

在這里插入圖片描述

在上述代碼中,創(chuàng)建了一個管道ch,并在另一個goroutine中等待3秒后向管道寫入數(shù)據(jù)。
在主goroutine中使用select語句監(jiān)聽兩個管道:一個是剛剛創(chuàng)建的ch,另一個是time.After函數(shù)返回的管道c。
由于ch管道3秒后才會有數(shù)據(jù)寫入,而time.After函數(shù)是2秒超時,所以2秒后select會先收到管道c里的數(shù)據(jù),執(zhí)行“timeout!!!”并退出。

二、Ticker定時器

Ticker定時器可以周期性地不斷觸發(fā)時間事件,不需要額外的Reset操作。Ticker的結構中也包含一個Time類型的管道C,每隔固定時間段d就會向該管道發(fā)送當前的時間,根據(jù)這個管道消息來觸發(fā)事件。

Ticker定時器是Go標準庫time包中的一個重要組件。它允許你每隔一定的時間間隔執(zhí)行一次指定的操作。Ticker定時器在創(chuàng)建時會啟動一個后臺goroutine,該goroutine會按照指定的時間間隔不斷向一個通道(Channel)發(fā)送當前的時間值。

1. 創(chuàng)建Ticker

要創(chuàng)建一個Ticker定時器,你可以使用time.NewTicker函數(shù)。這個函數(shù)接受一個time.Duration類型的參數(shù),表示時間間隔,并返回一個*time.Ticker類型的指針。
Ticker定時器的核心是一個通道(Channel),你可以通過監(jiān)聽這個通道來接收時間間隔到達的事件。

ticker := time.NewTicker(1 * time.Second)

上面的代碼創(chuàng)建了一個每隔1秒觸發(fā)一次的Ticker定時器。

2. 監(jiān)聽Ticker事件

要監(jiān)聽Ticker定時器的事件,你可以使用range關鍵字或者select語句來監(jiān)聽Ticker定時器的通道。每次時間間隔到達時,Ticker定時器的通道都會接收到一個當前的時間值。

for range ticker.C {  
    // 在這里執(zhí)行周期性任務  
}
package main

import (
    "fmt"
    "time"
)

func main() {
    ticker := time.NewTicker(1 * time.Second)
    //查看定時器數(shù)據(jù)類型
    fmt.Printf("定時器數(shù)據(jù)類型%T\n", ticker)
    //啟動協(xié)程來監(jiān)聽定時器觸發(fā)事件,通過time.Sleep函數(shù)來等待5秒鐘,然后調(diào)用ticker.Stop()函數(shù)來停止定時器。
    //最后,輸出"定時器停止"表示定時器已經(jīng)成功停止。
    go func() {
        for range ticker.C {
            fmt.Println("Ticker ticked")
        }

    }()

    //執(zhí)行5秒后,讓定時器停止
    time.Sleep(5 * time.Second)
    ticker.Stop()
    fmt.Println("定時器停止")
}

在這里插入圖片描述

或者,如果你需要同時監(jiān)聽多個通道,你可以使用select語句:

select {  
case t := <-ticker.C:  
    // 處理Ticker定時器事件  
case <-stopChan:  
    // 處理停止信號  
}
package main

import (
    "fmt"
    "time"
)

func main() {
    ticker := time.NewTicker(1 * time.Second) // 創(chuàng)建一個每秒觸發(fā)一次的Ticker定時器
    defer ticker.Stop()                       // 確保在main函數(shù)結束時停止定時器

    for {
        select {
        case t := <-ticker.C:
            fmt.Println("Tick at", t)
        }
    }
}

每秒執(zhí)行一次

在這里插入圖片描述

3. 停止Ticker定時器

當你不再需要Ticker定時器時,你應該調(diào)用它的Stop方法來停止它。停止Ticker定時器可以釋放與之關聯(lián)的資源,并防止不必要的goroutine繼續(xù)運行。
ticker.Stop()

停止Ticker定時器后,它的通道將不再接收任何事件。

package main

import (
    "fmt"
    "time"
)

func main() {
    ticker := time.NewTicker(500 * time.Millisecond) // 創(chuàng)建一個每500毫秒觸發(fā)一次的Ticker定時器
    timeEnd := make(chan bool)                       // 用于停止Ticker定時器的通道

    go func() {
        for {
            select {
            //當達到設置的停止條件式,停止循環(huán)
            case <-timeEnd:
                fmt.Println("===結束任務")
                break
            case t := <-ticker.C:
                fmt.Println("==500毫秒響應一次:", t)
            }
        }
    }()

    time.Sleep(5 * time.Second) // 主線程等待5秒鐘
    ticker.Stop()               // 停止Ticker定時器
    timeEnd <- true             // 發(fā)送結束信號

    fmt.Println("===定時任務結束===")
}

持續(xù)執(zhí)行5秒后,定時器停止運行

在這里插入圖片描述

三、定時器應用案例

1. 定時打印日志

Ticker定時器的一個常見應用是定時打印日志。通過設置一個Ticker定時器,你可以每隔固定的時間間隔輸出一次日志信息,從而監(jiān)控程序的運行狀態(tài)。

package main

import (
    "fmt"
    "time"
)

func main() {
    ticker := time.NewTicker(5 * time.Second)
    defer ticker.Stop() // 確保程序結束時停止Ticker定時器

    for range ticker.C {
        // 打印當前時間作為日志
        fmt.Println("Current time:", time.Now())
    }
}

5秒打印一次

在這里插入圖片描述

在這個例子中,我們創(chuàng)建了一個每隔5秒觸發(fā)一次的Ticker定時器,并在一個無限循環(huán)中監(jiān)聽它的事件。
每次事件觸發(fā)時,我們都會打印當前的時間作為日志信息。注意,由于我們在main函數(shù)中使用了defer語句來確保Ticker定時器在程序結束時被停止,所以即使循環(huán)是無限的,程序也不會因為Ticker定時器而泄漏資源。

然而,在實際應用中,你可能需要在某個條件下提前停止Ticker定時器。這時,你可以使用一個額外的通道來發(fā)送停止信號:

package main

import (
    "fmt"
    "time"
)

func main() {
    ticker := time.NewTicker(5 * time.Second)
    stopChan := make(chan struct{})

    go func() {
        // 模擬一個運行一段時間的任務
        time.Sleep(15 * time.Second)
        // 發(fā)送停止信號
        stopChan <- struct{}{}
    }()

    for {
        select {
        case t := <-ticker.C:
            fmt.Println("Tick at", t)
        case <-stopChan:
            fmt.Println("Ticker stopped")
            ticker.Stop()
            return
        }
    }
}

在這里插入圖片描述

在這個例子中,我們創(chuàng)建了一個額外的stopChan通道來發(fā)送停止信號。我們啟動了一個goroutine來模擬一個運行一段時間的任務,并在任務完成后向stopChan發(fā)送一個停止信號。
在for循環(huán)中,我們使用select語句同時監(jiān)聽Ticker定時器的通道和stopChan通道。當接收到停止信號時,我們停止Ticker定時器并退出程序。

2. 周期性檢查系統(tǒng)狀態(tài)

Ticker定時器還可以用于周期性檢查系統(tǒng)狀態(tài)。例如,你可以每隔一段時間檢查一次服務器的負載、內(nèi)存使用情況或數(shù)據(jù)庫連接數(shù)等關鍵指標,并在發(fā)現(xiàn)異常時采取相應的措施。

package main

import (
    "fmt"
    "math/rand"
    "time"
)

// 模擬檢查系統(tǒng)狀態(tài)的函數(shù)
func checkSystemStatus() {
    // 這里可以添加實際的檢查邏輯
    // 例如:檢查CPU使用率、內(nèi)存使用情況等
    // 這里我們隨機生成一個0到100之間的數(shù)作為模擬結果
    status := rand.Intn(101)
    fmt.Printf("System status: %d\n", status)

    // 假設狀態(tài)大于80表示系統(tǒng)異常
    if status > 80 {
        fmt.Println("Warning: System status is above normal!")
        // 這里可以添加處理異常的邏輯
        // 例如:發(fā)送警報、重啟服務等
    }
}

func main() {
    ticker := time.NewTicker(10 * time.Second)
    defer ticker.Stop() // 確保程序結束時停止Ticker定時器

    for range ticker.C {
        checkSystemStatus()
    }
}

在這里插入圖片描述

在這個例子中,我們創(chuàng)建了一個每隔10秒觸發(fā)一次的Ticker定時器,并在一個無限循環(huán)中監(jiān)聽它的事件。
每次事件觸發(fā)時,我們都會調(diào)用checkSystemStatus函數(shù)來模擬檢查系統(tǒng)狀態(tài)。checkSystemStatus函數(shù)會隨機生成一個0到100之間的數(shù)作為模擬結果,并根據(jù)結果判斷是否系統(tǒng)異常。
如果系統(tǒng)異常(即狀態(tài)大于80),則打印警告信息,并可以在這里添加處理異常的邏輯。

同樣地,你可以使用額外的通道來發(fā)送停止信號,以便在需要時提前停止Ticker定時器。

四、總結

本文詳細介紹了Go語言中Timer和Ticker兩種定時器的用法,并通過實際案例展示了它們的應用場景。Timer定時器適用于需要一次性觸發(fā)的事件,而Ticker定時器適用于需要周期性觸發(fā)的事件

到此這篇關于Go語言中的定時器原理與實戰(zhàn)應用的文章就介紹到這了,更多相關Go語言 定時器內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

  • Go語言Handler詳細說明

    Go語言Handler詳細說明

    這篇文章主要介紹了Go語言Handler詳細說明,Handler用于處理請求并給予響應。更嚴格地說,用來讀取請求體、并將請求對應的響應字段(respones header)寫入ResponseWriter中,需要的朋友可以參考下
    2022-04-04
  • 在Visual Studio Code中配置GO開發(fā)環(huán)境的詳細教程

    在Visual Studio Code中配置GO開發(fā)環(huán)境的詳細教程

    這篇文章主要介紹了在Visual Studio Code中配置GO開發(fā)環(huán)境的詳細教程,需要的朋友可以參考下
    2017-02-02
  • 關于go get 下載第三方包存儲路徑問題

    關于go get 下載第三方包存儲路徑問題

    這篇文章主要介紹了關于go get 下載第三方包存儲路徑問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2024-01-01
  • Go設計模式之原型模式圖文詳解

    Go設計模式之原型模式圖文詳解

    原型模式是一種創(chuàng)建型設計模式, 使你能夠復制已有對象, 而又無需使代碼依賴它們所屬的類,本文將通過圖片和文字讓大家可以詳細的了解Go的原型模式,感興趣的通過跟著小編一起來看看吧
    2023-07-07
  • golang中sync.Mutex的實現(xiàn)方法

    golang中sync.Mutex的實現(xiàn)方法

    本文主要介紹了golang中sync.Mutex的實現(xiàn)方法,mutex?主要有兩個?method:?Lock()?和?Unlock(),文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2022-04-04
  • Go結構體從基礎到應用深度探索

    Go結構體從基礎到應用深度探索

    本文深入探討了結構體的定義、類型、字面量表示和使用方法,旨在為讀者呈現(xiàn)Go結構體的全面視角,通過結構體,開發(fā)者可以實現(xiàn)更加模塊化、高效的代碼設計,這篇文章旨在為您提供關于結構體的深入理解,助您更好地利用Go語言的強大功能
    2023-10-10
  • 使用Golang進行比較版本號大小

    使用Golang進行比較版本號大小

    在日常開發(fā)中,比較版本號大小的情況是經(jīng)常遇到的,這篇文章主要為大家詳細介紹了如何使用Golang進行比較版本號大小,需要的小伙伴可以參考下
    2024-01-01
  • go值賦值和引用賦值的使用

    go值賦值和引用賦值的使用

    本文將介紹Go語言中的值賦值和引用賦值,并比較它們之間的差異,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2023-10-10
  • Golang中int類型和字符串類型相互轉換的實現(xiàn)方法

    Golang中int類型和字符串類型相互轉換的實現(xiàn)方法

    在日常開發(fā)中,經(jīng)常需要將數(shù)字轉換為字符串或者將字符串轉換為數(shù)字,在 Golang 中,有一些很簡便的方法可以實現(xiàn)這個功能,接下來就詳細講解一下如何實現(xiàn) int 類型和字符串類型之間的互相轉換,需要的朋友可以參考下
    2023-09-09
  • GO語言開發(fā)終端命令行小工具改進更新

    GO語言開發(fā)終端命令行小工具改進更新

    這篇文章主要為大家介紹了GO語言開發(fā)終端命令行小工具的改進更新,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2024-01-01

最新評論