一、案例
先看上面一段代码,子协程要在 100个小时候退出,导致主协程始终卡在那边。
func TestCancel1(t *testing.T) { wg := sync.WaitGroup{} wg.Add(1) go func() { t.Log("goroutine 1") time.Sleep(100 * time.Hour) wg.Done() }() wg.Wait() t.Log("goroutine main")}
输入:
可见主协程始终 期待状态,没发退出。
二、应用context.WithTimeout,给协程一个退出工夫
咱们在上面的代码里,写了一个context.WithTimeout给3秒,3秒后这个程序没有执行完就退出。
func TestTimeout(t *testing.T) { wg := sync.WaitGroup{} wg.Add(1) parentContext := context.Background() cancelCtx, cancelFunc := context.WithTimeout(parentContext, time.Second*3) go func(ctx context.Context) { for { t.Log("goroutine 1") select { case <-cancelCtx.Done(): wg.Done() return case <-time.After(time.Hour * 100): wg.Done() } } }(cancelCtx) wg.Wait() cancelFunc() t.Log("goroutine main")}
三、应用context.WithCancel,在子协程退出
func TestCancel2(t *testing.T) { wg := sync.WaitGroup{} wg.Add(1) parentContext := context.Background() cancelCtx, cancelFunc := context.WithCancel(parentContext) go func(ctx context.Context) { for { select { case <-cancelCtx.Done(): return case <-time.After(time.Hour * 100): cancelFunc() wg.Done() case <-time.After(time.Second * 3): cancelFunc() wg.Done() } t.Log("goroutine 1") } }(cancelCtx) wg.Wait() t.Log("goroutine main")}
输入:
goroutine 1goroutine main