通常咱們導入import ("time")包,而後調用time.NewTicker(1 * time.Second) 實現一個定時器:函數
func timer1() { timer1 := time.NewTicker(1 * time.Second) for { select { case <-timer1.C: xxx() //執行咱們想要的操做 } } }
再看看timer包中NewTicker的具體實現:ui
func NewTicker(d Duration) *Ticker { if d <= 0 { panic(errors.New("non-positive interval for NewTicker")) } // Give the channel a 1-element time buffer. // If the client falls behind while reading, we drop ticks // on the floor until the client catches up. c := make(chan Time, 1) t := &Ticker{ C: c, r: runtimeTimer{ when: when(d), period: int64(d), f: sendTime, arg: c, }, } startTimer(&t.r) return t }
其中Ticker的具體struct以下:code
type Ticker struct { C <-chan Time // The channel on which the ticks are delivered. r runtimeTimer }
Ticker中的C爲數據類型爲Time的單向管道,只能讀,不能寫事件
再分下一下runtimeTimer的參數:element
r: runtimeTimer{ when: when(d), period: int64(d), f: sendTime, arg: c, }
其中sendTime爲回調函數,startTimer時候註冊的,arg爲回調函數須要的參數argget
startTimer(&t.r)
再進一步看看startTimer的實現:回調函數
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: } }
經過往管道里面寫時間,注意咱們Ticker結構裏面的C是單向管道,只能讀不能寫,那要怎麼寫數據了it
經過類型轉化,由於channel是一個原生類型,所以不只支持被傳遞,還支持類型轉換,裝換成雙向的管道channel,往裏面寫數據,用戶API那邊提供的是單向管道,用戶只能就只能讀數據,就至關於一層限制io
最後,調用執行具體xxx函數,實現定時執行某些事件的功能:import
for { select { case <-timer1.C: xxxx() } }