Функция context.WithCancelCause
Функция context.WithCancelCause создает новый производный контекст
на основе родительского. В отличие от context.WithCancel,
она позволяет передать причину отмены в виде ошибки.
Первый параметр функции — родительский контекст, от которого
будет создан производный. Функция возвращает три значения:
производный контекст, функцию отмены с причиной и функцию,
которая позволяет получить текущую причину отмены.
Синтаксис
ctx, cancelCause := context.WithCancelCause(parent)
Пример
Давайте создадим контекст с возможностью отмены по причине:
package main
import (
"context"
"fmt"
)
func main() {
ctx, cancelCause := context.WithCancelCause(context.Background())
// Отменяем контекст с указанием причины
cancelCause(fmt.Errorf("timeout exceeded"))
// Получаем причину отмены
err := context.Cause(ctx)
fmt.Println(err)
}
Результат выполнения кода:
"timeout exceeded"
Пример
Рассмотрим пример с горутиной, которая выполняет работу до отмены:
package main
import (
"context"
"fmt"
"time"
)
func main() {
ctx, cancelCause := context.WithCancelCause(context.Background())
go func() {
for {
select {
case <-ctx.Done():
fmt.Println("Work stopped:", context.Cause(ctx))
return
default:
fmt.Println("Working...")
time.Sleep(500 * time.Millisecond)
}
}
}()
time.Sleep(2 * time.Second)
cancelCause(fmt.Errorf("manual stop"))
time.Sleep(500 * time.Millisecond)
}
Результат выполнения кода:
"Working..."
"Working..."
"Working..."
"Working..."
"Work stopped: manual stop"
Пример
Покажем, как отменить контекст с причиной, и как получить эту причину:
package main
import (
"context"
"errors"
"fmt"
)
func main() {
ctx, cancelCause := context.WithCancelCause(context.Background())
// Отменяем с конкретной ошибкой
cancelCause(errors.New("connection lost"))
// Проверяем причину
if err := context.Cause(ctx); err != nil {
fmt.Println("Error:", err)
}
}
Результат выполнения кода:
"Error: connection lost"
Пример
Использование с таймаутом для контроля времени выполнения:
package main
import (
"context"
"fmt"
"time"
)
func main() {
ctx, cancelCause := context.WithCancelCause(context.Background())
go func() {
select {
case <-time.After(3 * time.Second):
cancelCause(fmt.Errorf("operation timed out"))
}
}()
time.Sleep(2 * time.Second)
err := context.Cause(ctx)
if err != nil {
fmt.Println("Context cancelled:", err)
} else {
fmt.Println("Context is still active")
}
}
Результат выполнения кода:
"Context is still active"
Смотрите также
-
функцию
context.WithCancel,
которая создает контекст с отменой без указания причины -
функцию
context.Cause,
которая возвращает причину отмены контекста -
функцию
context.WithTimeout,
которая создает контекст с таймаутом -
функцию
context.WithDeadline,
которая создает контекст с дедлайном