一般我们导入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那边提供的是单向管道,用户只能就只能读数据,就相当于一层限制
for{ select{ case<-timer1.C: xxxx() } }