context.WithTimeout
和time.After
都能够很轻易地实现。func doBadthing(done chan bool) { time.Sleep(time.Second) done <- true } func timeout(f func(chan bool)) error { done := make(chan bool) go f(done) select { case <-done: fmt.Println("done") return nil case <-time.After(time.Millisecond): return fmt.Errorf("timeout") } } // timeout(doBadthing)
对于这段代码,会出现超时,子协程是不能够全部正常退出的。参见如何退出协程 goroutine 超时场景
func doGoodthing(done chan bool) { time.Sleep(time.Second) select { case done <- true: default: return } }
如果发送失败则,会直接退出。
3.拆分任务,分为多段,配合select使用,判断哪一段超时。
goroutine 被设计为不可以从外部无条件地结束掉,只能通过 channel 来与它通信。也就是说,每一个 goroutine 都需要承担自己退出的责任。(A goroutine cannot be programmatically killed. It can only commit a cooperative suicide.)
如何退出协程 goroutine 超时场景