Concurrency-safe task scheduler
There is no need for the default clause in Schedule.worker.
Memory side, it is better to create a time.Timer object and call Timer.Reset &amp; Timer.Stop on it.
No need for the done variable, we can just return when we are done.


func (s *Schedule) worker(c chan Task, i int) {
    t := time.NewTimer(s.idle * time.Second)
    for {
        select {
        case task := &lt;-c:
            task.Execute()
            if !t.Stop() {
                &lt;-t.C
            }
            t.Reset(s.idle * time.Second)
        case &lt;-t.C:
            s.Lock()
            close(c)
            delete(s.queues, i)
            s.Unlock()
            return
         }
    }
}



It is not advisable to close a channel from a receiver. Better to close the channel when you know that there are no more tasks and have the worker wait for that.


func (s *Schedule) worker(c chan Task, i int) {
    for task := range c {
        task.Execute()
    }
}