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

Go語言中Timer計(jì)時器的使用技巧詳解

 更新時間:2023年07月25日 10:56:26   作者:cainmusic  
Go語言中的time包里有個Timer計(jì)時器的功能,這篇文章主要就是來和大家介紹一下Timer計(jì)時器的使用技巧,感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下

time包里有個Timer計(jì)時器的功能,主要的結(jié)構(gòu)和函數(shù)有:

type Timer struct {
    C <-chan Time
    r runtimeTimer
}
func After(d Duration) <-chan Time
func AfterFunc(d Duration, f func()) *Timer
func NewTimer(d Duration) *Timer
func (*Timer) Reset(d Duration) bool
func (*Timer) Stop() bool

三個基本用法:

c := time.After(time.Second)
fmt.Println(<-c)
t := time.NewTimer(time.Second)
fmt.Println(<-t.C)
tc := make(chan int)
time.AfterFunc(time.Second, func() { tc <- 1 })
fmt.Println(<-tc)

After函數(shù)實(shí)際就是return NewTimer(d).C,和NewTimer的用法類似,但Timer本身還有Reset、Stop等方法可用,有相關(guān)需求的,應(yīng)使用NewTimer。

AfterFunc相當(dāng)于在d Duration之后創(chuàng)建了一個執(zhí)行f的goroutine,返回的Timer本身并不會阻塞,也不能像前面的例子那樣使用Timer.C,但可以使用Reset、Stop等方法。

導(dǎo)致上面區(qū)別的原因在于使用NewTimerAfterFunc生成計(jì)時器的時候,內(nèi)部使用的調(diào)用參數(shù)并不相同。

NewTimer:

func NewTimer(d Duration) *Timer {
    c := make(chan Time, 1)
    t := &Timer{
        C: c,
        r: runtimeTimer{
            when: when(d),
            f:    sendTime,
            arg:  c,
        },
    }
    startTimer(&t.r)
    return t
}
func sendTime(c interface{}, seq uintptr) {
    // Non-blocking send of time on c.
    // Used in NewTimer, it cannot block anyway (buffer).
    // Used in NewTicker, dropping sends on the floor is
    // the desired behavior when the reader gets behind,
    // because the sends are periodic.
    select {
    case c.(chan Time) <- Now():
    default:
    }
}

NewTimer在計(jì)時器完成時使用sendTime函數(shù),非阻塞的向Timer.C中傳入當(dāng)前時間,所以在計(jì)時器完成時,可以從其中獲取內(nèi)容。

AfterFunc:

func AfterFunc(d Duration, f func()) *Timer {
    t := &Timer{
        r: runtimeTimer{
            when: when(d),
            f:    goFunc,
            arg:  f,
        },
    }
    startTimer(&t.r)
    return t
}
func goFunc(arg interface{}, seq uintptr) {
    go arg.(func())()
}

AfterFunc則是在計(jì)時器完成時調(diào)用goFunc,在goFunc中啟動一個執(zhí)行參數(shù)f的goroutine,而并未對Timer.C進(jìn)行任何操作,于是我們無法從其中獲取內(nèi)容。

注:下面的內(nèi)容主要基于NewTimer創(chuàng)建的Timer

Timer使用的關(guān)鍵點(diǎn):

一,在一些任務(wù)中我們需要多次重復(fù)計(jì)時,不要使用循環(huán)創(chuàng)建大量計(jì)時器,會影響性能,盡量使用ResetStop來復(fù)用已創(chuàng)建的計(jì)時器。

二,TimerStop方法并不會關(guān)閉Timer.C,可能會導(dǎo)致意外的阻塞,如:

func main() {
    timer := time.NewTimer(time.Second)
    go func() {
        timer.Stop()
    }()
    <-timer.C
}

會導(dǎo)致程序阻塞,無法退出。

關(guān)于TimerResetStop的使用小技巧:

// 用下面的非阻塞方法使用Stop
func timerStop(t *time.Timer) {
    if !t.Stop() {
        select {
        case <-t.C:
        default:
        }
    }
}
// Reset之前先執(zhí)行Stop
func timerReset(t *time.Timer, d time.Duration) {
    timerStop(t)
    t.Reset(d)
}

關(guān)于Reset之前為何要Stop,time包的Reset文檔如下說:

For a Timer created with NewTimer, Reset should be invoked only on stopped or expired timers with drained channels.

對于使用NewTimer創(chuàng)建的Timer,Reset應(yīng)該用在已經(jīng)停止或過期,并已經(jīng)排空管道的計(jì)時器上。

If a program has already received a value from t.C, the timer is known to have expired and the channel drained, so t.Reset can be used directly. If a program has not yet received a value from t.C, however, the timer must be stopped and—if Stop reports that the timer expired before being stopped—the channel explicitly drained:

如果一個程序已經(jīng)從t.C中接收了值,計(jì)時器過期了并且管道已被排空,Reset可以直接使用。但如果程序還未從t.C中接收值,而計(jì)時器需要被停止,并且Stop方法報(bào)告計(jì)時器在被停止前已經(jīng)過期,則管道需要被顯式的排空:

if !t.Stop() {
    <-t.C
}
t.Reset(d)

This should not be done concurrent to other receives from the Timer's channel.

這個操作不應(yīng)與其他程序接收計(jì)時器的管道同時發(fā)生。

注意,上面的內(nèi)容其實(shí)還沒表述完全。

如果我們需要停止一個計(jì)時器,并且計(jì)時器的Stop方法報(bào)告為false時,計(jì)時器的狀態(tài),以及t.C的狀態(tài),共有三種可能:

  • Stop前已經(jīng)被Stop,t.C為空
  • Stop前已經(jīng)過期,計(jì)時器向t.C中寫入內(nèi)容,t.C為滿
  • Stop前已經(jīng)過期,計(jì)時器向t.C中寫入內(nèi)容,t.C的信息已被其他程序接收,t.C為空

前面文檔中的程序,僅在第2種情況會按照預(yù)期運(yùn)行。

其他兩種情況,顯式排空<-t.C的時候會阻塞。

就是因?yàn)樯厦娴那闆r,才演化出前面的timerStop函數(shù)。

但同時應(yīng)該明白,timerStop函數(shù)對應(yīng)上面幾種情況時如何處理:

  • select走default分支,跳過阻塞,但應(yīng)考慮到計(jì)時器并不是當(dāng)前Stop停止的
  • select進(jìn)行顯式排空,但應(yīng)考慮到計(jì)時器并未被成功停止,并且t.C的內(nèi)容被拋棄了
  • select走default分支,跳過阻塞,但應(yīng)考慮到計(jì)時器并未被成功停止,并且t.C的內(nèi)容被其他程序利用了

充分的考慮到上面這幾點(diǎn),就可以使用timerStop函數(shù)了。

否則,應(yīng)該充分考慮自己程序的需求,進(jìn)行必要的修改。

到此這篇關(guān)于Go語言中Timer計(jì)時器的使用技巧詳解的文章就介紹到這了,更多相關(guān)Go Timer計(jì)時器內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • VS?Code安裝go插件失敗原因分析以及解決方案

    VS?Code安裝go插件失敗原因分析以及解決方案

    vscode安裝go插件時,由于各種原因,在安裝插件時總是失敗,下面這篇文章主要給大家介紹了關(guān)于VS?Code安裝go插件失敗原因分析以及解決的相關(guān)資料,文中通過實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2022-09-09
  • goland 斷點(diǎn)調(diào)試顯示“變量不可用”的問題解決

    goland 斷點(diǎn)調(diào)試顯示“變量不可用”的問題解決

    本文主要介紹了goland 斷點(diǎn)調(diào)試顯示“變量不可用”的問題解決,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2025-11-11
  • Go整合ElasticSearch的示例代碼

    Go整合ElasticSearch的示例代碼

    這篇文章主要介紹了Go整合ElasticSearch的相關(guān)知識,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2023-07-07
  • Golang構(gòu)建WebSocket服務(wù)器和客戶端的示例詳解

    Golang構(gòu)建WebSocket服務(wù)器和客戶端的示例詳解

    這篇文章主要為大家詳細(xì)介紹了如何使用Go語言構(gòu)建WebSocket服務(wù)器和客戶端,以實(shí)現(xiàn)雙向通信,文中的示例代碼講解詳細(xì),需要的小伙伴可以參考一下
    2023-11-11
  • 一文詳解Go語言中的Defer機(jī)制

    一文詳解Go語言中的Defer機(jī)制

    在Go語言中,defer是一個關(guān)鍵字,用于確保資源的清理和釋放,特別是在函數(shù)中創(chuàng)建的資源,下面就跟隨小編一起來了解下Defer機(jī)制的具體使用吧
    2024-11-11
  • Go語言配置解析庫viper的使用指南

    Go語言配置解析庫viper的使用指南

    viper?配置管理解析庫,是由大神?Steve?Francia?開發(fā),本文就來和大家詳細(xì)講講它的具體使用,文中的示例代碼講解詳細(xì),需要的可以收藏一下
    2023-06-06
  • go語言中讀取配置文件的方法總結(jié)

    go語言中讀取配置文件的方法總結(jié)

    這篇文章主要為大家詳細(xì)介紹了go語言中讀取配置文件的幾個常見方法,文中的示例代碼講解詳細(xì),具有一定的借鑒價值,需要的小伙伴可以參考下
    2023-08-08
  • Golang內(nèi)存管理之內(nèi)存分配器詳解

    Golang內(nèi)存管理之內(nèi)存分配器詳解

    Go內(nèi)存分配器的設(shè)計(jì)思想來源于TCMalloc,全稱是Thread-Caching?Malloc,核心思想是把內(nèi)存分為多級管理,下面就來和大家深入聊聊Go語言內(nèi)存分配器的使用吧
    2023-06-06
  • go語言通過zlib壓縮數(shù)據(jù)的方法

    go語言通過zlib壓縮數(shù)據(jù)的方法

    這篇文章主要介紹了go語言通過zlib壓縮數(shù)據(jù)的方法,實(shí)例分析了Go語言中zlib的使用技巧,需要的朋友可以參考下
    2015-03-03
  • GO語言gin框架實(shí)現(xiàn)管理員認(rèn)證登陸接口

    GO語言gin框架實(shí)現(xiàn)管理員認(rèn)證登陸接口

    這篇文章主要介紹了GO語言gin框架實(shí)現(xiàn)管理員認(rèn)證登陸接口,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2020-10-10

最新評論

绥阳县| 苏尼特左旗| 禄丰县| 阳江市| 岑溪市| 绵竹市| 奉化市| 都匀市| 泗阳县| 石屏县| 重庆市| 和硕县| 永和县| 枣阳市| 勃利县| 宜兴市| 晋宁县| 旬邑县| 牡丹江市| 嘉祥县| 南郑县| 张家口市| 鄂温| 南汇区| 新津县| 杭锦后旗| 新巴尔虎左旗| 罗田县| 商洛市| 温州市| 佛教| 梅河口市| 徐汇区| 丽水市| 肥东县| 枣强县| 平陆县| 新闻| 辽阳市| 同德县| 道真|