共计 1099 个字符,预计需要花费 3 分钟才能阅读完成。
一、案例
先看上面一段代码,子协程要在 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 1 | |
goroutine main |
正文完