MST

星途 面试题库

面试题:Go中context的WithTimeout和WithDeadline的区别及应用场景

在Go语言中,context包提供了WithTimeout和WithDeadline两个函数来设置上下文的截止时间。请详细阐述这两个函数的区别,以及在多协程任务管理中,它们各自适用于哪些不同的应用场景。同时,请通过编写代码示例来展示如何正确使用这两个函数以实现高效的任务管理。
11.7万 热度难度
编程语言Go

知识考点

AI 面试

面试题答案

一键面试

区别

  1. WithTimeout:根据传入的相对时间来设置截止时间,即从调用WithTimeout的时间点开始,经过指定的时间段后截止。它更侧重于任务执行的时长限制。
  2. WithDeadline:根据传入的绝对时间来设置截止时间,明确指定某个具体的时间点为截止时间。它更侧重于在某个特定时间前完成任务。

应用场景

  1. WithTimeout
    • 适用于对任务执行时长有明确限制的场景,例如网络请求,如果超过一定时间没有响应,就取消请求。
    • 当任务的截止时间是基于开始执行后的一段时间时,使用WithTimeout更方便。
  2. 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秒),同样,当协程执行到截止时间还未完成时,会被取消。