Аккаунт Войти / Регистрация
Тема
Размер текста
Channel direction and select patterns in Go vs Java | Patterns, idioms, and best practices in Go

Channel direction and select patterns in Go vs Java | Patterns, idioms, and best practices in Go

1. Channel direction — channel directions

In Go, channels can be one-way: only for sending or receiving. This helps to make function interfaces more safe and clear. For a Java developer, this is somewhat similar to BlockingQueue<Integer>, where producer/consumer use different methods put/take.


// Go: one-way channels
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();
One-way channels improve readability and protect against accidental sending or receiving in the wrong place.

2. Select patterns with default

select allows non-blocking waiting for multiple channels, including default, to avoid blocking the goroutine. In Java, you have to combine poll(timeout) or check the queue manually.


// Go: select with default
select {
case val := <-ch1:
    fmt.Println("Received from ch1:", val)
case val := <-ch2:
    fmt.Println("Received from ch2:", val)
default:
    fmt.Println("Nothing is ready, continuing to work")
}

// Java: non-blocking check
Integer val1 = queue1.poll();
Integer val2 = queue2.poll();
if (val1 != null) {
    System.out.println("Received from queue1: " + val1);
} else if (val2 != null) {
    System.out.println("Received from queue2: " + val2);
} else {
    System.out.println("Nothing is ready, continuing to work");
}
Select with default allows goroutines to continue execution without blocking, which is especially useful for fan-in/fan-out and timeouts.

3. Comparison Table Go vs Java

Concept Go Java Comment
Unidirectional Channels chan <- or <- chan BlockingQueue<Integer> with put/take Explicit separation of sending and receiving increases code safety
Select select with case and optional default poll() + checking multiple queues Go allows non-blocking waiting on multiple channels simultaneously
Default / non-blocking mode case default in select poll() without blocking Allows goroutine to continue without stopping when no data is available
Fan-in / Fan-out select + channels + goroutine ExecutorService + queues + manual checking Go simplifies the pattern and makes it safe for concurrency

Conclusion

Channels and select are key tools in Go for safe and efficient concurrent data processing. The direction of channels makes function interfaces safe and readable, while select with default helps avoid blocking and conveniently merge data from multiple sources. For Java developers, they are analogous to BlockingQueue with put/take and poll(), but Go provides a more lightweight and expressive syntax for concurrent patterns.

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

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

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

Asynchrony and Reactivity in Java: CompletableFuture, Flow, and Virtual Threads
In modern Java development, there are three main approaches to asynchrony and concurrency: CompletableFuture — for single asynchronous tasks. Flow / Reactive Streams — for data flows with backpressur…
Low-level mechanisms - part 2 | Go ↔ Java
In this article, we gathered the key low-level mechanisms of Go that most often raise questions for developers coming from Java. We will consider: unsafe.Pointer, struct alignment, pointer arithmetic,…
Scheduler internals in Go ↔ Java: how your code is actually executed
When you write go func() or create a Thread in Java, it seems like you are managing concurrency. But in reality, you are passing the task to the scheduler. And this is where the real show begins. Go…

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

Concurrency is not about “starting many threads”. It’s about agreements between them. Imagine a restaurant kitchen: — cooks (threads / goroutines) — orders (tasks) — and the main question: how do th…
When HashMap starts killing production: the engineering story of ConcurrentHashMap
Imagine a typical production service. 32 CPU hundreds of threads configuration / session / rate limits cache tens of thousands of operations per second And somewhere inside — a regular Map. At first…
Zero Allocation in Java: what it is and why it matters
Zero Allocation — is an approach to writing code in which no unnecessary objects are created in heap memory during runtime. The main idea: fewer objects → less GC → higher stability and performance. …