面试题答案
一键面试区别
- WithTimeout:根据传入的相对时间来设置截止时间,即从调用
WithTimeout
的时间点开始,经过指定的时间段后截止。它更侧重于任务执行的时长限制。 - WithDeadline:根据传入的绝对时间来设置截止时间,明确指定某个具体的时间点为截止时间。它更侧重于在某个特定时间前完成任务。
应用场景
- WithTimeout:
- 适用于对任务执行时长有明确限制的场景,例如网络请求,如果超过一定时间没有响应,就取消请求。
- 当任务的截止时间是基于开始执行后的一段时间时,使用
WithTimeout
更方便。
- WithDeadline:
- 适用于需要在某个特定时间点前完成任务的场景,比如在某个整点前完成数据同步任务。
- 当截止时间是基于外部时间因素(如系统时钟的某个时间点)而不是任务开始后的时长时,使用
WithDeadline
更合适。
代码示例
package main
import (
"context"
"fmt"
"time"
)
func main() {
// WithTimeout示例
ctxTimeout, cancelTimeout := context.WithTimeout(context.Background(), 2*time.Second)
defer cancelTimeout()
go func(ctx context.Context) {
select {
case <-time.After(3 * time.Second):
fmt.Println("WithTimeout: task finished after 3s (expected cancel)")
case <-ctxTimeout.Done():
fmt.Println("WithTimeout: task cancelled due to timeout")
}
}(ctxTimeout)
time.Sleep(3 * time.Second)
// WithDeadline示例
deadline := time.Now().Add(2 * time.Second)
ctxDeadline, cancelDeadline := context.WithDeadline(context.Background(), deadline)
defer cancelDeadline()
go func(ctx context.Context) {
select {
case <-time.After(3 * time.Second):
fmt.Println("WithDeadline: task finished after 3s (expected cancel)")
case <-ctxDeadline.Done():
fmt.Println("WithDeadline: task cancelled due to deadline")
}
}(ctxDeadline)
time.Sleep(3 * time.Second)
}
在上述代码中:
WithTimeout
示例中,创建了一个2秒超时的上下文,当协程执行超过2秒还未完成时,会被取消。WithDeadline
示例中,设置了一个绝对截止时间(当前时间+2秒),同样,当协程执行到截止时间还未完成时,会被取消。