Функция context.WithoutCancel
Функция context.WithoutCancel создает новый контекст на основе родительского,
который не отменяется при отмене родительского контекста. В первый параметр
мы передаем родительский контекст, от которого нужно отвязаться. Функция
возвращает новый контекст, который не содержит сигнала отмены и не
наследует таймаут или дедлайн от родителя. Это полезно, когда нужно
выполнить операцию, которая не должна прерываться при отмене основного
контекста, например, запись логов или финализация операций.
Синтаксис
context.WithoutCancel(parent context.Context) context.Context
Пример
Давайте создадим контекст с отменой и дочерний контекст без отмены, затем отменим родительский контекст и проверим, завершится ли работа дочернего контекста:
package main
import (
"context"
"fmt"
"time"
)
func main() {
ctx, cancel := context.WithCancel(context.Background())
noCancelCtx := context.WithoutCancel(ctx)
go func() {
select {
case <-noCancelCtx.Done():
fmt.Println("noCancelCtx done")
case <-time.After(2 * time.Second):
fmt.Println("noCancelCtx still running")
}
}()
time.Sleep(500 * time.Millisecond)
cancel()
time.Sleep(3 * time.Second)
}
Результат выполнения кода:
"noCancelCtx still running"
Как видно из примера, дочерний контекст не завершился после отмены
родительского контекста, потому что WithoutCancel создает контекст,
который игнорирует сигналы отмены родителя.
Пример
Давайте создадим контекст с таймаутом и контекст без отмены на его основе, затем проверим, что время жизни дочернего контекста не ограничено таймаутом родителя:
package main
import (
"context"
"fmt"
"time"
)
func main() {
ctx, cancel := context.WithTimeout(context.Background(), 1*time.Second)
defer cancel()
noCancelCtx := context.WithoutCancel(ctx)
go func() {
select {
case <-noCancelCtx.Done():
fmt.Println("noCancelCtx done")
case <-time.After(3 * time.Second):
fmt.Println("noCancelCtx completed after 3s")
}
}()
time.Sleep(4 * time.Second)
}
Результат выполнения кода:
"noCancelCtx completed after 3s"
Дочерний контекст продолжает работу даже после истечения таймаута родительского контекста, что демонстрирует полную независимость от механизмов отмены родителя.
Пример
Давайте проверим, что у контекста, созданного через WithoutCancel,
метод Done всегда возвращает nil, что означает отсутствие
сигнала отмены:
package main
import (
"context"
"fmt"
)
func main() {
ctx, cancel := context.WithCancel(context.Background())
noCancelCtx := context.WithoutCancel(ctx)
if noCancelCtx.Done() == nil {
fmt.Println("Done returns nil")
}
cancel()
if noCancelCtx.Err() == nil {
fmt.Println("Err returns nil")
}
}
Результат выполнения кода:
"Done returns nil"
"Err returns nil"
Этот пример показывает, что контекст, созданный через WithoutCancel,
полностью отвязан от механизма отмены: канал Done равен nil,
и метод Err всегда возвращает nil даже после отмены
родительского контекста.
Смотрите также
-
функцию
context.Context,
которая определяет интерфейс контекста -
функцию
context.WithCancel,
которая создает контекст с функцией отмены -
функцию
context.WithTimeout,
которая создает контекст с таймаутом -
функцию
context.Background,
которая возвращает пустой контекст