func timerproc(tb *timersBucket) {
   for{
      lock(&tb.lock) //加锁
      now := nanotime()  //当前时间的纳秒值
      delta := int64(-1)  //最近要执行的timer和当前时间的差值
      for{
         iflen(tb.t) == 0{
            delta = -1
            break
         }//当前无可执行timer,直接跳出该循环
         t := tb.t[0] 
         delta = t.when - now //取when组小的的timer,计算于当前时间的差值
         ifdelta > 0{
            break
         }// delta大于0,说明还未到发送channel时间,需要跳出循环去睡眠delta时间
         ift.period > 0{
            // leave in heap but adjust next time to fire
            t.when += t.period * (1+ -delta/t.period)// 计算该timer下次执行任务的时间
            siftdownTimer(tb.t, 0) //调整堆
         } else{
            // remove from heap,如果没有设定下次执行时间,则将该timer从堆中移除(time.after和time.sleep函数即是只执行一次定时任务)
            last := len(tb.t) - 1
            iflast > 0{
               tb.t[0] = tb.t[last]
               tb.t[0].i = 0
            }
            tb.t[last] = nil
            tb.t = tb.t[:last]
            iflast > 0{
               siftdownTimer(tb.t, 0)
            }
            t.i = -1// mark as removed
         }
         f := t.f
         arg := t.arg
         seq := t.seq
         unlock(&tb.lock)//解锁
         f(arg, seq) //在channel中发送time结构体,唤醒阻塞的协程
         lock(&tb.lock)
      }
      ifdelta < 0{
         // No timers left - put goroutine to sleep.
         goparkunlock(&tb.lock, "timer goroutine (idle)", traceEvGoBlock, 1)
         continue
      }// delta小于0说明当前无定时任务,直接进行阻塞进行睡眠
      tb.sleeping = true
      tb.sleepUntil = now + delta
      unlock(&tb.lock)
      notetsleepg(&tb.waitnote, delta)  //睡眠delta时间,唤醒之后就可以执行在堆顶的定时任务了
   }
}