功能说明
该示例把取消与截止时间作为一等参数沿调用链传递。fetch 把实际工作放到独立 goroutine 执行,并用 select 在结果与上下文完成之间等待;一旦上下文被取消或超时,调用立即返回,而工作 goroutine 因持有同一上下文也应在检查取消后尽快退出。
关键代码
结果通道容量为一,保证即便调用方在上下文先完成而不再接收时,工作 goroutine 也能写入而不泄漏——若通道无缓冲,它会被永久阻塞。WithDeadline 只是对标准库 WithTimeout 的封装,强调截止时间由父上下文派生,取消能向下传播。返回专门的 ErrTimeout,让调用方区分超时与业务错误。
使用注意
取消是协作式的:work 内部必须在合适位置检查 ctx.Done() 或把 ctx 继续传给下游,否则 goroutine 会继续运行直至自然结束,取消形同虚设。不要在取消后假设副作用已经回滚,写入类工作应保证幂等或自行处理部分完成。永远应当调用返回的 cancel 函数以释放定时器与关联资源,即便超时已经发生。
代码示例
package request
import (
"context"
"errors"
"time"
)
var ErrTimeout = errors.New("request timed out")
type Result struct {
Value int
Err error
}
func fetch(ctx context.Context, work func(context.Context) (int, error)) (int, error) {
resultCh := make(chan Result, 1)
go func() {
value, err := work(ctx)
resultCh <- Result{Value: value, Err: err}
}()
select {
case <-ctx.Done():
return 0, ErrTimeout
case result := <-resultCh:
return result.Value, result.Err
}
}
func WithDeadline(parent context.Context, timeout time.Duration) (context.Context, context.CancelFunc) {
return context.WithTimeout(parent, timeout)
}