阻塞的协程如何超时退出?

func main() {
	ctx, cancel := context.WithTimeout(context.TODO(), time.Second*3)
	defer cancel() // 防止任务比超时时间短导致资源未释放
	// 启动协程
	go task(ctx)
	// 主协程需要等待,否则直接退出
	time.Sleep(time.Second * 10)
}

func task(ctx context.Context) {
	ch := make(chan struct{}, 0)
	// 真正的任务协程
	go func() {
		// 模拟两秒耗时任务
		time.Sleep(time.Second * 6)
		//
		fmt.Println("任务处理完成")
		ch <- struct{}{}
	}()
	select {
	case <-ch:
		fmt.Println("done")
	case <-ctx.Done():
		fmt.Println("timeout")
	}
}

我这个WithTimeout的上下文时间超时了,为啥还会打印任务处理完成这句话?
正确的应该怎么修改

共 2 个回复


hapiman

你的主协程不是一直等着子协程处理完成吗,你把时间调整一下不就行了。

# 0

vHbl

粗略讲, go的线程都是独立的, 没有父子关系.

go func() {
		// 模拟两秒耗时任务
		time.Sleep(time.Second * 6)
		//
		fmt.Println("任务处理完成")
		ch <- struct{}{}
	}()

所以这个线程也是独立的.

# 1