Назад к вопросам
Junior
132
questionbank
Что такое контекст в Go?
Sobes Copilot
Получайте ответы в реальном времени
Ответ от нейросети
sobes.tech AI
Контекст (context.Context) в Go — объект, который несет дедлайн, сигнал отмены (cancellation signal) и данные, специфичные для запроса. Используется для управления жизненным циклом горутин и передачи информации между ними в процессе выполнения одного запроса/операции.
Основные характеристики:
- Потокобезопасен: Может безопасно передаваться между горутинами.
- Иммутабелен: Once created, a
Contextcannot be changed. Деривативные контексты создаются на основе родительского. - Иерархичен: Контексты образуют дерево с корнем (
context.Background()илиcontext.TODO()). Отмена родительского контекста приводит к отмене всех дочерних.
Основные функции пакета context:
context.Background(): Пустой контекст, обычно используется в main-функции, в верхнеуровневых запросах или при тестировании. Не отменен никогда.context.TODO(): Также пустой контекст. Используется как заглушка, когда неизвестно, какой контекст использовать, или если функциональность контекста еще не реализована.context.WithCancel(parent Context): Возвращает новый дочерний контекст и функцию отмены. Вызов функции отмены отменяет этот контекст и все его дочерние контексты.context.WithDeadline(parent Context, deadline time.Time): Возвращает дочерний контекст, который автоматически отменяется, когда наступает указанное время. Также возвращает функцию отмены для ручной отмены.context.WithTimeout(parent Context, timeout time.Duration): То же, что иWithDeadline, но с указанием длительности.context.WithValue(parent Context, key, val interface{}): Возвращает дочерний контекст с присвоенным значением по ключу.
Применение:
- Отмена операций: Например, таймаут HTTP-запроса или прерывание длительной операции.
- Передача данных: Например, ID запроса для логирования, аутентификационная информация.
Пример использования context.WithTimeout:
package main
import (
"context"
"fmt"
"time"
)
func longRunningOperation(ctx context.Context, resultChan chan string) {
select {
case <-time.After(3 * time.Second):
// Операция завершилась успешно
resultChan <- "Operation completed"
case <-ctx.Done():
// Контекст был отменен
err := ctx.Err() // Получаем причину отмены
resultChan <- fmt.Sprintf("Operation cancelled: %v", err)
}
}
func main() {
// Создаем контекст с таймаутом 2 секунды
ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second)
defer cancel() // Гарантируем вызов отмены
resultChan := make(chan string, 1)
go longRunningOperation(ctx, resultChan)
// Ждем результат или отмену
select {
case res := <-resultChan:
fmt.Println(res)
case <-ctx.Done():
fmt.Printf("Main context done: %v\n", ctx.Err())
}
// Ждем немного, чтобы горутина успела завершиться, если была отменена
time.Sleep(1 * time.Second)
}
В этом примере longRunningOperation проверяет контекст на отмену. Если таймаут основного контекста (2 секунды) истекает раньше, чем завершится itself (3 секунды), горутина получает сигнал отмены через ctx.Done() и завершается.