Ошибка context.DeadlineExceeded
Ошибка context.DeadlineExceeded возникает, когда контекст превышает
установленный срок выполнения операции. Эта ошибка возвращается функцией
Context.Err после того, как истекло время, установленное с помощью
context.WithTimeout или context.WithDeadline. Ошибка
информирует о том, что операция не успела завершиться в отведенное время.
Синтаксис
Ошибка context.DeadlineExceeded является предопределенной переменной
пакета context. Она реализует интерфейс error и может быть
использована для проверки причины завершения контекста:
if errors.Is(ctx.Err(), context.DeadlineExceeded) {
// обработка превышения времени
}
Также можно сравнивать ошибку с предопределенной переменной:
if ctx.Err() == context.DeadlineExceeded {
// обработка превышения времени
}
Пример использования с таймаутом
Создадим контекст с таймаутом в 1 секунду и выполним операцию, которая занимает 2 секунды:
package main
import (
"context"
"fmt"
"time"
)
func main() {
ctx, cancel := context.WithTimeout(context.Background(), 1*time.Second)
defer cancel()
select {
case <-time.After(2 * time.Second):
fmt.Println("Operation completed")
case <-ctx.Done():
fmt.Println(ctx.Err())
}
}
Результат выполнения кода:
"context deadline exceeded"
В этом примере операция не успевает завершиться за 1 секунду,
и контекст возвращает ошибку context.DeadlineExceeded.
Пример с жестким дедлайном
Установим конкретное время завершения операции с помощью
context.WithDeadline:
package main
import (
"context"
"fmt"
"time"
)
func main() {
deadline := time.Now().Add(500 * time.Millisecond)
ctx, cancel := context.WithDeadline(context.Background(), deadline)
defer cancel()
select {
case <-time.After(1 * time.Second):
fmt.Println("Operation completed")
case <-ctx.Done():
fmt.Println(ctx.Err())
}
}
Результат выполнения кода:
"context deadline exceeded"
Обработка ошибки в горутинах
При работе с горутинами важно проверять ошибку контекста и корректно завершать выполнение:
package main
import (
"context"
"errors"
"fmt"
"time"
)
func doWork(ctx context.Context) error {
select {
case <-time.After(3 * time.Second):
return nil
case <-ctx.Done():
return ctx.Err()
}
}
func main() {
ctx, cancel := context.WithTimeout(context.Background(), 1*time.Second)
defer cancel()
err := doWork(ctx)
if errors.Is(err, context.DeadlineExceeded) {
fmt.Println("Timeout exceeded")
} else if err != nil {
fmt.Println("Other error:", err)
} else {
fmt.Println("Work completed successfully")
}
}
Результат выполнения кода:
"Timeout exceeded"
Сравнение с context.Canceled
Важно различать context.DeadlineExceeded и context.Canceled.
Первая возникает при превышении времени, вторая - при явной отмене:
package main
import (
"context"
"fmt"
"time"
)
func main() {
ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second)
defer cancel()
go func() {
time.Sleep(500 * time.Millisecond)
cancel()
}()
select {
case <-time.After(3 * time.Second):
fmt.Println("Operation completed")
case <-ctx.Done():
fmt.Println(ctx.Err())
}
}
Результат выполнения кода:
"context canceled"
В этом примере контекст был отменен явно до истечения таймаута,
поэтому возвращается ошибка context.Canceled.
Смотрите также
-
функцию
context.WithTimeout,
которая создает контекст с таймаутом -
функцию
context.WithDeadline,
которая создает контекст с дедлайном -
ошибку
context.Canceled,
которая возникает при явной отмене контекста -
функцию
Context.Err,
которая возвращает причину завершения контекста