golang中timer定时器实现原理

前端之家收集整理的这篇文章主要介绍了golang中timer定时器实现原理前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。

一般我们导入import ("time")包,然后调用time.NewTicker(1 * time.Second) 实现一个定时器:

functimer1(){
	timer1:=time.NewTicker(1*time.Second)
	for{
		select{
		case<-timer1.C:
			xxx()//执行我们想要的操作
		}
	}
}

再看看timer包中NewTicker的具体实现:

funcNewTicker(dDuration)*Ticker{
	ifd<=0{
		panic(errors.New("non-positiveintervalforNewTicker"))
	}
	//Givethechannela1-elementtimebuffer.
	//Iftheclientfallsbehindwhilereading,wedropticks
	//ontheflooruntiltheclientcatchesup.
	c:=make(chanTime,1)
	t:=&Ticker{
		C:c,r:runtimeTimer{
			when:when(d),period:int64(d),f:sendTime,arg:c,},}
	startTimer(&t.r)
	returnt
}

其中Ticker的具体struct如下:

typeTickerstruct{
	C<-chanTime//Thechannelonwhichtheticksaredelivered.
	rruntimeTimer
}

Ticker中的C为数据类型为Time的单向管道,只能读,不能写

再分下一下runtimeTimer的参数:

r:runtimeTimer{
			when:when(d),}

其中sendTime为回调函数,startTimer时候注册的,arg为回调函数需要的参数arg

startTimer(&t.r)

再进一步看看startTimer的实现:

funcsendTime(cinterface{},sequintptr){
	//Non-blockingsendoftimeonc.
	//UsedinNewTimer,itcannotblockanyway(buffer).
	//UsedinNewTicker,droppingsendsontheflooris
	//thedesiredbehaviorwhenthereadergetsbehind,//becausethesendsareperiodic.
	select{
	casec.(chanTime)<-Now():
	default:
	}
}

通过往管道里面写时间,注意我们Ticker结构里面的C是单向管道,只能读不能写,那要怎么写数据了

通过类型转化,因为channel是一个原生类型,因此不仅支持被传递,还支持类型转换,装换成双向的管道channel,往里面

写数据,用户API那边提供的是单向管道,用户只能就只能读数据,就相当于一层限制


最后,调用执行具体xxx函数,实现定时执行某些事件的功能

for{
select{
	case<-timer1.C:
	xxxx()
}
}

猜你在找的Go相关文章