Аккаунт Войти / Регистрация
Тема
Размер текста
Channel direction и select patterns в Go vs Java | Паттерны, идиомы и лучшие практики Go

Channel direction и select patterns в Go vs Java | Паттерны, идиомы и лучшие практики Go

1. Channel direction — направление каналов

В Go каналы могут быть односторонними: только для отправки или получения. Это помогает делать интерфейсы функций более безопасными и ясными. Для Java-разработчика это частично похоже на BlockingQueue<Integer>, где producer/consumer используют разные методы put/take.


// Go: односторонние каналы
func sender(ch chan<- int) {
    ch <- 42
}

func receiver(ch <-chan int) {
    value := <-ch
    fmt.Println("Received:", value)
}

ch := make(chan int)
go sender(ch)
go receiver(ch)

// Java: BlockingQueue
BlockingQueue<Integer> queue = new LinkedBlockingQueue<>();

Runnable producer = () -> queue.put(42);
Runnable consumer = () -> {
    Integer value = queue.take();
    System.out.println("Received: " + value);
};
new Thread(producer).start();
new Thread(consumer).start();
Односторонние каналы повышают читаемость и защищают от случайной отправки или получения в неправильном месте.

2. Select patterns с default

select позволяет неблокирующе ожидать сразу несколько каналов, включая default, чтобы не блокировать goroutine. В Java приходится комбинировать poll(timeout) или проверять очередь вручную.


// Go: select с default
select {
case val := <-ch1:
    fmt.Println("Получено из ch1:", val)
case val := <-ch2:
    fmt.Println("Получено из ch2:", val)
default:
    fmt.Println("Ничего не готово, продолжаем работать")
}

// Java: неблокирующая проверка
Integer val1 = queue1.poll();
Integer val2 = queue2.poll();
if (val1 != null) {
    System.out.println("Получено из queue1: " + val1);
} else if (val2 != null) {
    System.out.println("Получено из queue2: " + val2);
} else {
    System.out.println("Ничего не готово, продолжаем работать");
}
Select с default позволяет goroutine продолжать выполнение без блокировки, что особенно полезно для fan-in/fan-out и таймаутов.

3. Таблица сравнения Go vs Java

Концепт Go Java Комментарий
Односторонние каналы chan <- или <- chan BlockingQueue<Integer> с put/take Явное разделение отправки и получения повышает безопасность кода
Select select с case и optional default poll() + проверка нескольких очередей Go позволяет неблокирующе ждать несколько каналов одновременно
Default / неблокирующий режим case default в select poll() без блокировки Позволяет goroutine не останавливаться при отсутствии данных
Fan-in / Fan-out select + каналы + goroutine ExecutorService + очереди + ручная проверка Go упрощает паттерн и делает его безопасным для параллельности

Итог

Каналы и select — ключевые инструменты Go для безопасной и эффективной параллельной обработки данных. Направление каналов делает интерфейсы функций безопасными и читаемыми, а select с default позволяет избежать блокировок и удобно объединять данные из нескольких источников. Для Java-разработчиков аналогичны BlockingQueue с put/take и poll(), но Go обеспечивает более лёгкий и выразительный синтаксис для concurrent паттернов.

Оставить комментарий

Мой канал в социальных сетях
Отправляя email, вы принимаете условия политики конфиденциальности

Полезные статьи:

Основы параллельности в Go для Java-разработчиков | Сoncurrency часть 1
Если вы Java-разработчик, привыкший к потокам и ExecutorService, Go предлагает более лёгкий и удобный подход к параллельной обработке — goroutine и каналы. В этой статье мы разберём ключевые концепции…
Atomic vs Mutex, Blocking vs Non‑Blocking, Read/Write Splitting (RWMutex), Logging | Concurrency Patterns и Best Practices  часть 5 | Go ↔ Java
В этой статье мы разберём ключевые подходы к работе с параллелизмом и синхронизацией в Go и Java. Мы сравним, как одни и те же задачи решаются на этих языках, покажем идиомы, паттерны и лучшие практик…
Stream vs For в Java: как писать максимально быстрый код
В Java производительность часто определяется не «красотой кода», а тем, как именно он взаимодействует с памятью, JIT-компилятором и CPU cache. Разберём, почему обычный for часто быстрее Stream, и как …

Новые статьи:

Конкурентность — это не про «запустить много потоков». Это про договорённости между ними. Представь кухню ресторана: — повара (потоки / горутины) — заказы (задачи) — и главный вопрос: как они коорди…
История начинается не с академической теории, а с типичной production-проблемы. Представьте сервис: 48 CPU 300+ потоков нагрузка 200k операций в секунду много shared state Команда использует обы…
Когда HashMap начинает убивать продакшн: инженерная история ConcurrentHashMap
Представьте обычный продакшн-сервис. 32 CPU сотни потоков кэш конфигурации / сессий / rate limits десятки тысяч операций в секунду И где-то внутри — обычный Map. Сначала всё выглядит безобидно. Map&…