一、案例
先看下面一段代码,子协程要在 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
                                    相关文章
暂无评论...
