Skip to content

可取消任务 ​

难度:⭐⭐ 中等 ​

考点 ​

  • context.WithCancel 取消传播
  • 任务中断与清理
  • 心跳模式

提示 ​

  1. LongTask 每步用 select 检查 ctx.Done()
  2. TaskWithCleanup 用 defer 确保 cleanup 执行
  3. Heartbeat 后台 goroutine + ticker + select ctx.Done()

参考答案(Go) ​

点击展开参考答案
go
//go:build ignore

package answer

import (
	"context"
	"time"
)

func LongTask(ctx context.Context, steps int, stepDuration time.Duration) (int, error) {
	for i := 0; i < steps; i++ {
		select {
		case <-ctx.Done():
			return i, ctx.Err()
		case <-time.After(stepDuration):
		}
	}
	return steps, nil
}

func TaskWithCleanup(ctx context.Context, work func(ctx context.Context) error, cleanup func()) error {
	defer cleanup()
	return work(ctx)
}

func Heartbeat(ctx context.Context, interval time.Duration) <-chan time.Time {
	ch := make(chan time.Time)
	go func() {
		defer close(ch)
		ticker := time.NewTicker(interval)
		defer ticker.Stop()
		for {
			select {
			case t := <-ticker.C:
				select {
				case ch <- t:
				case <-ctx.Done():
					return
				}
			case <-ctx.Done():
				return
			}
		}
	}()
	return ch
}

持续学习,持续构建。