欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Golang當(dāng)中的定時(shí)器實(shí)例詳解

 更新時(shí)間:2023年07月10日 08:35:50   作者:一個(gè)山里的少年  
這篇文章主要給大家介紹了關(guān)于Golang當(dāng)中定時(shí)器的相關(guān)資料,定時(shí)器的實(shí)現(xiàn)大家應(yīng)該都遇到過(guò),最近在學(xué)習(xí)golang,文中通過(guò)實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下

前言

在平時(shí)寫(xiě)代碼的時(shí)候,我們經(jīng)常會(huì)遇到在將來(lái)某個(gè)時(shí)間點(diǎn)或者間隔一段時(shí)間重復(fù)執(zhí)行函數(shù)。這個(gè)時(shí)候我們就可以考慮使用定時(shí)器。本片文章主要介紹一下golang當(dāng)中的幾個(gè)常用的定時(shí)器。time.Timer,time.Ticker,time.After以及time.AfterFunc和time.Ticker的基本使用

定時(shí)器的基本使用

golang當(dāng)中的定時(shí)器有這個(gè)一次性的定時(shí)器(Timer)和周期性的定時(shí)器(Ticker).在平時(shí)的編程當(dāng)中經(jīng)常會(huì)使用timer當(dāng)中的ticker,AfterFunc定時(shí)器,而NewTicker是每隔多長(zhǎng)時(shí)間觸發(fā),NewTimer是等待多長(zhǎng)時(shí)間觸發(fā)一次請(qǐng)注意是只觸發(fā)一次。請(qǐng)注意一下兩者的區(qū)別。
下面我們來(lái)首先來(lái)使用一下這兩個(gè)定時(shí)器首先是這個(gè)Timer定時(shí)器

package main

import (
	"fmt"
	"time"
)
func main() {
	myTimer := time.NewTimer(time.Second * 3) //初始化定時(shí)器
	var i = 0
	for {
		select {
		case <-myTimer.C:
			i++
			fmt.Printf("the counter is%d", i)
			myTimer.Reset(time.Second * 3) //注意需要重新設(shè)置
		}
	}
	myTimer.Stop() //不在使用需要將其停止
}

注意這個(gè)timer定時(shí)器超時(shí)之后需要重新進(jìn)行設(shè)置,才能重新觸發(fā)。如果上面的代碼我們沒(méi)有Reset,那么就會(huì)導(dǎo)致死鎖。其實(shí)我們也可以看看這個(gè)Timer是怎么是實(shí)現(xiàn)的

func NewTimer(d Duration) *Timer {
    c := make(chan Time, 1)
    t := &Timer{
        C: c,  // 信道
        r: runtimeTimer{
            when: when(d),  // 觸發(fā)時(shí)間
            f:    sendTime, // 時(shí)間到了之后的調(diào)用函數(shù)
            arg:  c,        // 調(diào)用sendTime時(shí)的入?yún)?
        },
    }
    startTimer(&t.r)  // 把定時(shí)器的r字段放入由定時(shí)器維護(hù)協(xié)程維護(hù)的堆中
    return t
} 

從上面的構(gòu)造函數(shù)中可以大概看出定時(shí)器的工作流程,這里面最重要的是runtimeTimer。構(gòu)造定時(shí)器的時(shí)候會(huì)把runtimeTimer放入由定時(shí)器維護(hù)協(xié)程維護(hù)的堆中,當(dāng)時(shí)間到了之后,維護(hù)協(xié)程把r從堆中移除,并調(diào)用r的sendTime函數(shù),sendTime的入?yún)⑹嵌〞r(shí)器的信道C??梢酝茢?,sendTime中執(zhí)行的邏輯應(yīng)該是向信道C中推送時(shí)間,通知上游系統(tǒng)時(shí)間到了,而事實(shí)正是如此:

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():  //時(shí)間到了之后把當(dāng)前時(shí)間放入信道中
    default:
    }
} 

其實(shí)這個(gè)time.After就是對(duì)這個(gè)time.Timer的一個(gè)封裝,所以如果我們上面使用這個(gè)time.After那么會(huì)頻繁的創(chuàng)建time.Timer對(duì)象
下面我們?cè)趤?lái)看一下這個(gè)time.AterFunc()定時(shí)器。

Golang當(dāng)中的AfterFunc函數(shù)用于等待經(jīng)過(guò)時(shí)間,此后在其自己的協(xié)程當(dāng)中調(diào)用定義的函數(shù)f.函數(shù)在時(shí)間包下定義。下面我們一起看看如何使用這個(gè)

import (
	"fmt"
	"time"
)

func main() {
	f := func() {
		fmt.Println("the func is call after 3 second")
	}
	myTime := time.AfterFunc(time.Second*3, f)

	defer myTime.Stop() //定時(shí)器不用了需要關(guān)閉
	time.Sleep(time.Second * 4)
}

下面我們?cè)诳纯催@個(gè)time.NewTicker定時(shí)器的使用

package main

import (
	"fmt"
	"time"
)

func main() {
	mytick := time.NewTicker(time.Second * 2)
	defer mytick.Stop() //定時(shí)器不用了需要關(guān)閉
	done := make(chan struct{})
	go func() {
		for {
			time.Sleep(time.Second * 10)
			done <- struct{}{}
		}
	}()
	for {
		select {
		case <-done:
			fmt.Println("done!!!!")
			return
		case t := <-mytick.C:
			fmt.Printf("the curtime is %v\n", t)
		}
	}

}

下面我們來(lái)看一下這個(gè)陷阱,這個(gè)需要注意

package main
import (
	"fmt"
	"time"
)
func main() {
	var count int
	for {
		select {
		case <-time.Tick(time.Second * 1):
			fmt.Println("case1")
			count++
			fmt.Println("count--->", count)
		case <-time.Tick(time.Second * 2):
			fmt.Println("case2")
			count++
			fmt.Println("count--->", count)
		}
	}
}

這個(gè)代碼是有陷阱的,下面我們來(lái)看看這個(gè)運(yùn)行結(jié)果是什么?

可見(jiàn) case2 永遠(yuǎn)沒(méi)有被執(zhí)行到,問(wèn)題就出在代碼邏輯上,首先看time.Tick方法。我們可以看一下這個(gè)方法就知道

func Tick(d Duration) <-chan Time {
	if d <= 0 {
		return nil
	}
	return NewTicker(d).C
}

它每次都會(huì)創(chuàng)建一個(gè)新的定時(shí)器,隨著 for 循環(huán)進(jìn)行, select 始終監(jiān)聽(tīng)兩個(gè)新創(chuàng)建的定時(shí)器,老的定時(shí)器被拋棄掉了,也就不會(huì)去讀取老定時(shí)器中的通道。

select 可以同時(shí)監(jiān)聽(tīng)多個(gè)通道,誰(shuí)先到達(dá)就先讀取誰(shuí),如果同時(shí)有多個(gè)通道有消息到達(dá),那么會(huì)隨機(jī)讀取一個(gè)通道,其他的通道由于沒(méi)有被讀取,所以數(shù)據(jù)不會(huì)丟失,需要循環(huán)調(diào)用 select 來(lái)讀取剩下的通道。

總結(jié):

  • tick創(chuàng)建完成之后,不是馬上有一個(gè)tick.第一個(gè)tick在你設(shè)置的多少秒之后才會(huì)進(jìn)行創(chuàng)建
  • golang當(dāng)中的定時(shí)器實(shí)質(zhì)上是這個(gè)單項(xiàng)的管道
  • time.NewTicker會(huì)定時(shí)觸發(fā)任務(wù),當(dāng)下一次執(zhí)行到來(lái)而當(dāng)前任務(wù)畫(huà)面執(zhí)行完,會(huì)等待當(dāng)前任務(wù)執(zhí)行完畢在進(jìn)行下一次任務(wù)。
  • Ticker和Timer的不同之處是,Ticker時(shí)間到達(dá)之后不需要人為的調(diào)用Reset方法來(lái)重新設(shè)置時(shí)間

到此這篇關(guān)于Golang當(dāng)中的定時(shí)器的文章就介紹到這了,更多相關(guān)Golang定時(shí)器內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 解決電腦用GoLand太卡將VsCode定制成Go IDE步驟過(guò)程

    解決電腦用GoLand太卡將VsCode定制成Go IDE步驟過(guò)程

    這篇文章主要為大家介紹了解決電腦用GoLand太卡,將VsCode定制成Go IDE步驟過(guò)程詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-11-11
  • golang使用swagger的過(guò)程詳解

    golang使用swagger的過(guò)程詳解

    這篇文章主要介紹了golang使用swagger的過(guò)程詳解,本文給大家介紹的非常詳細(xì),感興趣的朋友跟隨小編一起看看吧
    2024-06-06
  • Go Gorm 示例詳解

    Go Gorm 示例詳解

    Gorm是一款高性能的Golang ORM庫(kù),便于開(kāi)發(fā)人員提高效率,本文介紹了Gorm的基本概念、數(shù)據(jù)庫(kù)連接、基本操作(創(chuàng)建表、新增記錄、查詢記錄、修改記錄、刪除記錄)等,本文介紹Go Gorm的相關(guān)知識(shí),感興趣的朋友一起看看吧
    2025-01-01
  • golang?日志庫(kù)ZAP[uber-go?zap]示例詳解

    golang?日志庫(kù)ZAP[uber-go?zap]示例詳解

    ZAP是由Uber開(kāi)源的高性能Go語(yǔ)言日志庫(kù),支持多種日志級(jí)別及基本信息打印,雖然ZAP本身不支持日志分割,但可以結(jié)合lumberjack進(jìn)行日志切割,實(shí)現(xiàn)日志按文件大小、時(shí)間或間隔切割等功能,ZAP提供Logger和SugaredLogger兩種日志記錄器
    2024-10-10
  • go語(yǔ)言中if語(yǔ)句用法實(shí)例

    go語(yǔ)言中if語(yǔ)句用法實(shí)例

    這篇文章主要介紹了go語(yǔ)言中if語(yǔ)句用法,以實(shí)例形式分析了if語(yǔ)句的定義及使用技巧,非常具有實(shí)用價(jià)值,需要的朋友可以參考下
    2015-02-02
  • Go語(yǔ)言提升開(kāi)發(fā)效率的語(yǔ)法糖技巧分享

    Go語(yǔ)言提升開(kāi)發(fā)效率的語(yǔ)法糖技巧分享

    每門(mén)語(yǔ)言都有自己的語(yǔ)法糖,像java的語(yǔ)法糖就有方法變長(zhǎng)參數(shù)、拆箱與裝箱、枚舉、for-each等等,Go語(yǔ)言也不例外。本文就來(lái)介紹一些Go語(yǔ)言的語(yǔ)法糖,需要的可以參考一下
    2022-07-07
  • go 代碼的調(diào)試---打印調(diào)用堆棧的實(shí)例

    go 代碼的調(diào)試---打印調(diào)用堆棧的實(shí)例

    下面小編就為大家?guī)?lái)一篇go 代碼的調(diào)試---打印調(diào)用堆棧的實(shí)例。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2017-10-10
  • Go Generate 代替 Makefile使用方法詳解

    Go Generate 代替 Makefile使用方法詳解

    這篇文章主要為大家介紹了Go Generate 代替 Makefile使用方法詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-12-12
  • Go打包二進(jìn)制文件的實(shí)現(xiàn)

    Go打包二進(jìn)制文件的實(shí)現(xiàn)

    這篇文章主要介紹了Go打包二進(jìn)制文件的實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2020-03-03
  • 三種Golang數(shù)組拷貝方式及性能分析詳解

    三種Golang數(shù)組拷貝方式及性能分析詳解

    在Go語(yǔ)言中,我們可以使用for、append()和copy()進(jìn)行數(shù)組拷貝。這篇文章主要為大家詳細(xì)介紹一下這三種方式的具體實(shí)現(xiàn)與性能分析,需要的可以參考一下
    2022-08-08

最新評(píng)論