1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74
| package common
import ( "errors" "os" "os/signal" "time" )
var ErrTimeOut = errors.New("执行者执行超时") var ErrInterrupt = errors.New("执行者被中断")
type Runner struct { tasks []func(int) //要执行的任务 complete chan error timeout <-chan time.Time interrupt chan os.Signal
}
func New(tm time.Duration) *Runner { return &Runner{ complete: make(chan error), timeout: time.After(tm), interrupt: make(chan os.Signal, 1), } }
func (r *Runner) Add(tasks ...func(int)) { r.tasks = append(r.tasks, tasks...) }
func (r *Runner) run() error { for id, task := range r.tasks { if r.isInterrupt() { return ErrInterrupt } task(id) } return nil }
func (r *Runner) isInterrupt() bool { select { case <-r.interrupt: signal.Stop(r.interrupt) return true default: return false } }
func (r *Runner) Start() error { signal.Notify(r.interrupt, os.Interrupt)
go func() { r.complete <- r.run() }()
select { case err := <-r.complete: return err case <-r.timeout: return ErrTimeOut } }
|
complete
是一个无缓冲通道,也就是同步通道,因为我们要使用它来控制我们整个程序是否终止,所以它必须是同步通道,要让main routine等待,一致要任务完成或者被强制终止。
interrupt
是一个有缓冲的通道,这样做是因为,我们可以至少接收到一个操作系统的中断信息,这样Go runtime在发送这个信号的时候不会被阻塞,如果是无缓冲的通道就会阻塞了。