Оглавление:
Context, propagation и cancellation patterns в Go vs Java | Паттерны, идиомы и лучшие практики Go
←
1. Context и его роль
В Go context.Context используется для передачи сигналов отмены и таймаутов между goroutine, а также для передачи значений (propagation). Для Java-разработчиков это частично похоже на Future с отменой, Thread.interrupt() и ThreadLocal.
// Go: базовый контекст с таймаутом
ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second)
defer cancel()
go func(ctx context.Context) {
select {
case <-time.After(5 * time.Second):
fmt.Println("Горрутина завершена")
case <-ctx.Done():
fmt.Println("Горрутина отменена:", ctx.Err())
}
}(ctx)
// Java: отмена через Future и ExecutorService
ExecutorService executor = Executors.newSingleThreadExecutor();
Future<?> f = executor.submit(() -> {
try {
Thread.sleep(5000);
System.out.println("Задача завершена");
} catch (InterruptedException e) {
System.out.println("Задача отменена");
}
});
f.cancel(true); // отмена
executor.shutdown();
Context помогает передавать сигналы отмены и таймауты между goroutine, что особенно важно в параллельных и сетевых задачах.
2. Context propagation
Значения можно передавать через контекст, чтобы все дочерние goroutine получали общую информацию без глобальных переменных.
// Go: передача значения через контекст
ctx := context.WithValue(context.Background(), "userID", 42)
go func(ctx context.Context) {
fmt.Println("UserID:", ctx.Value("userID"))
}(ctx)
// Java: ThreadLocal для передачи контекста
ThreadLocal<Integer> userID = ThreadLocal.withInitial(() -> 42);
Runnable task = () -> System.out.println("UserID: " + userID.get());
new Thread(task).start();
В Go context propagation упрощает передачу данных и сигналов отмены через иерархию goroutine, вместо глобальных переменных или сложных передач параметров.
3. Cancellation patterns
Контекст позволяет гибко отменять задачи. Основные подходы:
- timeout / deadline
- явная отмена через
cancel() - комбинация с select для неблокирующего ожидания
// Go: комбинированный пример fan-in с отменой
func worker(ctx context.Context, jobs <-chan int, results chan<- int) {
for {
select {
case j, ok := <-jobs:
if !ok { return }
results <- j * 2
case <-ctx.Done():
return
}
}
}
ctx, cancel := context.WithCancel(context.Background())
jobs := make(chan int)
results := make(chan int)
go worker(ctx, jobs, results)
// Отмена
cancel()
Используйте context для безопасной отмены всех связанных goroutine, особенно в fan-in/fan-out схемах.
4. Таблица сравнения Go vs Java
| Концепт | Go | Java | Комментарий |
|---|---|---|---|
| Отмена задачи | context с cancel(), таймаутами и deadline | Future.cancel(), Thread.interrupt() | Go позволяет безопасно и централизованно отменять все дочерние goroutine |
| Передача данных | context.WithValue() передает значения по иерархии goroutine | ThreadLocal или параметры метода | В Go меньше глобальных переменных, безопасно в параллельных задачах |
| Fan-in / Fan-out | goroutine + channels + select + context для отмены | ExecutorService + BlockingQueue + Future + ручная отмена | Go делает паттерн более лёгким и управляемым |
| Таймауты | context.WithTimeout / WithDeadline | Future.get(timeout), ScheduledExecutor | Контекст обеспечивает единый способ задания таймаутов для всей цепочки goroutine |
Итог
Использование context.Context — ключ к безопасной и управляемой параллельности в Go. Он объединяет три задачи:
- Передача данных между goroutine (propagation)
- Отмена задач (cancellation)
- Таймауты и deadlines
Для Java-разработчиков контекст аналогичен комбинации ThreadLocal + Future/interrupt + timeout. Go даёт более прямой, единый и безопасный механизм управления, особенно в схемах fan-in/fan-out.
Галерея
Мой канал в социальных сетях
Полезные статьи:
В современном Java-разработке есть три основных подхода к асинхронности и параллельности: CompletableFuture — для одиночных асинхронных задач. Flow / Reactive Streams — для потоков данных с контролем...
Java — Условные операторы Наглядная статья с примерами: if / else / логика / тернарный оператор / switch Кратко — условные операторы позволяют программе принимать решения: выполнить один кусок кода ...
← Связанные статьи: Часть 1 — Error handling и defer в Go (Параллельность и синхронизация) | Паттерны, идиомы и лучшие практики Go 1. Context и его роль В Go context.Context используется для пере...
Новые статьи:
Продолжаем серию статей для разработчиков, которые хотят изучить Go на основе знаний Java, и наоборот. В этой статье мы обсудим три ключевые темы: Resource Cleanup (освобождение ресурсов), Rate-Limiti...
Эта статья посвящена пониманию принципов работы с конкурентностью и синхронизацией в Go и Java. Мы рассмотрим ключевые подходы, такие как rate‑limiter, неблокирующие операции и планирование задач, сра...
Серия: Go для Java-разработчиков — разбор trace, профилирования и тестирования В этой статье мы разберем инструменты и практики для тестирования, отладки и профилирования в Go. Для Java-разработчика ...